欠損値の処理¶
欠損値とは¶
NumPyやpandasでは、データが存在しないことを表す欠損値として、NaN(非数値:Not A Number)を使います。 NaNが入ったデータを処理しても、基本的にエラーにはならず、結果もNaNになります。 欠損値は、欠測値ともいいます。
import numpy as np
data = [1, 3, np.nan]
print(sum(data) / 2) # nan
print(np.mean(data)) # nan
ただし、pandasやNumPyの一部の関数では、欠損値を除いて計算します。
import pandas as pd
print(pd.Series(data).mean()) # 2.0
print(np.nanmean(data)) # 2.0
欠損値の判定¶
pandas.DataFrame.isna, pandas.DataFrame.isnull, pandas.Series.isna, pandas.Series.isnull, numpy.isnan
で欠損値かどうか判定できます。
isnull
はisna
の別名で、全く同じものです。
欠損値の処理方法¶
欠損値を残したままの計算は、避けることが多いでしょう。 その場合、主に、次のどちらかの処理をします。
欠損値のデータを削除する。
欠損値を別の値で代替する。
欠損値のデータを削除する¶
pandasのdropna
で欠損値のデータを削除できます。
inplace=True
をつけると変数の中身を変更します。つけないと、変更せずに、欠損値を削除した新しいデータを作成します。
sr = pd.Series([1, 3, np.nan])
sr.dropna(inplace=True)
DataFrameの場合は、行単位か列単位をaxis
オプションで指定します。デフォルトは行単位で削除します。
Seriesと同じくinplace=True
をつけると変数の中身を変更します。
df = pd.DataFrame([[0, 1, 2], [1, 3, np.nan], [2, np.nan, 4]])
df.dropna() # 行単位に削除
df.dropna(axis=1) # 列単位に削除
欠損値を別の値で代替する¶
十分に根拠がある場合は、欠損値を別の値で代替する方法も取られます。
例その1:気温のセンサーデータに欠損値がある場合、急な気温の変動がないだろうと想定して、前後の値の平均値で代替する。
例その2:売上データに欠損値がある場合、見込みではなく確実な売上額が欲しいので、0で代替する。
例その3:風力のセンサーデータに欠損値がある場合、耐久試験用のデータが欲しいので、大きめの値で代替する。
平均値で代替すると、データはそれらしくなりますが、正しい値とは限らないので注意が必要です。 たとえば、株式投資でボラティリティ(変動率)を計算したいときに、欠損値を平均値で代替すると、本来のボラティリティより小さめの値となるでしょう。
pandasではfillna
で欠損値を別の値で代替できます。これまでと同様にinplace=True
をつけると変数の中身を変更します。
詳細は、pandas.DataFrame.fillnaか、後述の関連PyQを参照ください。
df.fillna(0) # 0で代替
df.fillna(method='ffill') # 直前の値で代替
df.fillna(df.mean()) # 平均で代替
scikit-learnではSimpleImputer
で欠損値を別の値で代替できます。
詳細は、Imputation of missing valuesを参照ください。
from sklearn.impute import SimpleImputer
imp = SimpleImputer()
imp.fit(df)
print(imp.transform(df))
※ scikit-learn 0.19 までは、sklearn.impute.SimpleImputer
の代わりにsklearn.preprocessing.Imputer
を使います。