pythonを使用してデータ分析を行う際には、前処理を必ず行います
前処理はそのデータ分析の8割を決定すると言われているくらい、重要な処理になります
そもそも前処理というのは、
蓄積されたデータを目的の作業(統計処理や機械学習など)を行うために、欠損値を処理したり、単位を揃えて綺麗にしたり、加工して使えるカタチにすることを指します
取得・蓄積されているデータがそのままで使えるということは、ほぼありません
そのため、前処理という作業が必要になってきます
今回の記事では、
pythonを使ってデータ分析を行う際の前処理について、理解を深めたい
そもそもpythonを使ってデータ分析を行う際の、前処理についてよくわからない
といった疑問を解決していきます
データ分析の前処理が理解できたら、実際にデータ分析・機械学習を行なっていきましょう
Pythonでデータ分析を始めよう!挫折しない実践ガイドでスキルアップ
Pythonで機械学習に学んで実装してみよう【サンプルコードあり】
Contents
pythonでデータ分析の前処理

前処理はそのデータ分析の8割を決定すると言われているくらい、重要な処理になります
そもそも前処理というのは、
蓄積されたデータを目的の作業(統計処理や機械学習など)を行うために、欠損値を処理したり、単位を揃えて綺麗にしたり、加工して使えるカタチにすることを指します
データ分析を行う際の前処理としては、以下のような手順になるかと思います
- 事前分析
- クリーニング
- 加工・変換
それぞれについてを解説していきたいと思います
pythonでデータ分析の前処理

まず最初に、どういった前処理が必要なのかを考えていく必要があります
そのためには、どういったデータなのか、データの代表値を確認、欠損値の有無の確認などを行なっていきます
今回はseabornに入っているirisのデータで行なっていきたいと思いますので、まずはデータを読み込んでおきます
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
print(iris)
>>>出力結果
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
.. ... ... ... ... ...
145 6.7 3.0 5.2 2.3 virginica
146 6.3 2.5 5.0 1.9 virginica
147 6.5 3.0 5.2 2.0 virginica
148 6.2 3.4 5.4 2.3 virginica
149 5.9 3.0 5.1 1.8 virginica
[150 rows x 5 columns]
事前分析を行う
事前分析では代表値や、データの型などを参照していきます
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#データ構成を確認
print(iris.info())
>>>出力結果
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal_length 150 non-null float64
1 sepal_width 150 non-null float64
2 petal_length 150 non-null float64
3 petal_width 150 non-null float64
4 species 150 non-null object
dtypes: float64(4), object(1)
memory usage: 6.0+ KB
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#行数と列数を確認
print(iris.shape)
>>>出力結果
(150, 5)
#行数だけ確認
print(len(iris))
>>>出力結果
150
#列数だけ確認
print(len(iris.columns))
>>>出力結果
5
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#インデックスの確認
print(iris.index)
>>>出力結果
RangeIndex(start=0, stop=150, step=1)
#カラム名の確認
print(iris.columns)
>>>出力結果
Index(['sepal_length', 'sepal_width', 'petal_length', 'petal_width',
'species'],
dtype='object')
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#DataFrameのデータ型を確認
print(iris.dtypes)
>>>出力結果
sepal_length float64
sepal_width float64
petal_length float64
petal_width float64
species object
dtype: object
欠損値の確認
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#データの欠損値を確認する
print(iris.isnull())
>>>出力結果
sepal_length sepal_width petal_length petal_width species
0 False False False False False
1 False False False False False
2 False False False False False
3 False False False False False
4 False False False False False
.. ... ... ... ... ...
145 False False False False False
146 False False False False False
147 False False False False False
148 False False False False False
149 False False False False False
[150 rows x 5 columns]
ちょっと見にくいので、もう少し簡潔にしていきます
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#欠損値をカラム名ごとにまとめて表示
print(iris.isnull().sum())
>>>出力結果
sepal_length 0
sepal_width 0
petal_length 0
petal_width 0
species 0
dtype: int64
欠損値の削除・置換
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
# 欠損値がひとつでも含まれている行を削除する
iris.dropna()
# ある行のすべての値が欠損していたら、その行を削除する
iris.dropna(subset=['列名'], how='all')
# すべての欠損値を0で置換する
iris.fillna(0)
csvで読み込んだ列ごとの平均値で欠損値を置換する
def data_mean():#欠損値に対してその列の平均値を置換
type = [("all file","*")]
file_path = filedialog.askopenfilename(filetypes = type, initialdir = os.getcwd ())
df = pd.read_csv(file_path, engine="python")
for i in df.columns:
mean=df[i].mean()
df[i].fillna(mean,inplace=True)
#欠損値を置換して、新規csvファイルを作成する
new_file_path = file_path + "_a" +".csv"
df.to_csv(new_file_path, index=False)
欠損値を無視する
# 計算の際に少しでも欠損値があると結果Nanになる。欠損値を無視するオプションを使う。
iris.sum(skipna=False)
iris.mean(skipna=False)
データの重複を確認する
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#重複を含まない値を確認
print(iris['sepal_length'].unique())
>>>出力結果
[5.1 4.9 4.7 4.6 5. 5.4 4.4 4.8 4.3 5.8 5.7 5.2 5.5 4.5 5.3 7. 6.4 6.9
6.5 6.3 6.6 5.9 6. 6.1 5.6 6.7 6.2 6.8 7.1 7.6 7.3 7.2 7.7 7.4 7.9]
要素の抽出
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#単一のデータを選択する
print(iris['sepal_length'])
>>>出力結果
0 5.1
1 4.9
2 4.7
3 4.6
4 5.0
145 6.7
146 6.3
147 6.5
148 6.2
149 5.9
Name: sepal_length, Length: 150, dtype: float64
import pandas as pd
import seaborn as sns
sns.set()
iris=sns.load_dataset("iris")
#複数のデータを選択する
print(iris[['sepal_length','sepal_width']])
>>>出力結果
sepal_length sepal_width
0 5.1 3.5
1 4.9 3.0
2 4.7 3.2
3 4.6 3.1
4 5.0 3.6
.. ... ...
145 6.7 3.0
146 6.3 2.5
147 6.5 3.0
148 6.2 3.4
149 5.9 3.0
[150 rows x 2 columns]
GUI上でキーワード指定して要素を抽出する
csvを読み込んで、GUI上でキーワード指定して要素を抽出することもできます
詳細は以下の記事を参考にしてください

import pandas as pd
import tkinter as tk
import os
from tkinter import filedialog
from scipy import stats
root=tk.Tk()
root.title("test")
root.geometry("800x600")
frame=tk.Frame()
frame.grid(row=0)
var=tk.StringVar()
var1=tk.StringVar()
text=tk.Entry(width=20,textvariable=var)
text.place(x=500,y=100)
listbox=tk.Listbox(frame,height=30,selectmode="single")
listbox.grid(row=1,column=1)
def fileselect():
global var
type = [("CSV file", "*.csv")]
file_path = tk.filedialog.askopenfilename(filetypes = type, initialdir = os.getcwd ())
csv_file = pd.read_csv(file_path, engine="python", index_col=None)
i = var.get()
if i in csv_file.columns:
word = csv_file.loc[:,i].values
listbox.insert(tk.END,word)
Button=tk.Button(frame,text="selectfile",command=fileselect,width=20)
Button.grid(row=3,column=1)
root.mainloop()
csvデータを使ってデータ分析のための前処理

サンプルのcsvを作成しているので、こちらを元に前処理を行なっていきます
csvデータの読み込み
import pandas as pd
df = pd.read_csv("sample.csv")
print(df)
>>>出力結果
Name Height weight
0 A 1.72m 72
1 B 171 71kg
2 C 168 62
3 D 1.56m NaN
4 E 1.72m 70kg
5 F 168cm 68
6 G 155cm 55kg
7 H 1.56m NaN
8 I 167 80kg
9 J 177 80
10 K 168 70kg
11 L NaN 58kg
12 M 1.41m 50kg
欠損値やら単位の違いやらがひどいデータを作っています
これを一から前処理していきましょう
単位を削除する
まずは単位を削除していきます
csvなら手打ちでやればいいじゃん、ってなりますが、これが100個くらいあったら大変ですよね
def height_to_num(Height):
if type(Height)==float:
return Height
if "cm" in Height:
Height = float(Height[:-2])
if (type(Height)!=float) and ("m" in Height):
Height = float(Height[:-1])
Height *= 100
return Height
def weight_to_num(weight):
if type(weight)==float:
return weight
if (type(weight)!=float) and ("kg" in weight):
weight = weight[:-2]
return float(weight)
df["Height"] = df.Height.apply(height_to_num)
df["weight"] = df.weight.apply(weight_to_num)
print(df)
>>>出力結果
Name Height weight
0 A 172 72.0
1 B 171 71.0
2 C 168 62.0
3 D 156 NaN
4 E 172 70.0
5 F 168 68.0
6 G 155 55.0
7 H 156 NaN
8 I 167 80.0
9 J 177 80.0
10 K 168 70.0
11 L NaN 58.0
12 M 141 50.0
欠損値を平均値で置換する
単位を削除することができたので、次は欠損値の処理を行っていきます
欠損値の処理は「fillna」で置換することができます
df.Height = df.Height.fillna(df.Height.mean())
df.weight = df.weight.fillna(df.weight.mean())
print(df)
>>>出力結果
Name Height weight
0 A 172 72.0
1 B 171 71.0
2 C 168 62.0
3 D 156 51.2
4 E 172 70.0
5 F 168 68.0
6 G 155 55.0
7 H 156 51.2
8 I 167 80.0
9 J 177 80.0
10 K 168 70.0
11 L 151 58.0
12 M 141 50.0
欠損値を削除する
欠損値の削除は「dropna()」を使用すれば可能です
print(df.dropna(how="any"))
>>>出力結果
Name Height weight
0 A 172 72.0
1 B 171 71.0
2 C 168 62.0
3 E 172 70.0
4 F 168 68.0
5 G 155 55.0
6 I 167 80.0
7 J 177 80.0
8 K 168 70.0
9 M 141 50.0
how=”any”では欠損ちが一つでも含まれる行・列を削除することになります
how=”all”では、すべての値が欠損値である行・列が削除されることになります
詳しくはpandasのreferenceを参照してください
まとめ

- データ分析の前処理はめちゃくちゃ大事
- 前処理を怠ると結果が大きく異なる
- 面倒なことはpythonに任せよう
おすすめプログラミングスクール(無料体験あり)
WEBCAMPを徹底解説している記事はこちら

アイデミープレミアムを徹底解説している記事はこちら

テックアカデミーを徹底解説している記事はこちら
