参考資料:
欠損値処理時の注意点:
まず以下の点を確認すること
- 欠損値の意味:
欠損値が必ずしも欠損値を示さず、ただの『該当無し』を示す場合がある。その場合は、欠損値として扱わず、該当なしであることを意味するように'None'とかの文字列とか、数値なら0で補完する。なので、まずは、変数毎にその欠損値の意味を確認すること! - 欠損値の数:
欠損値が15~20%以上あるような変数は、補完せずに削除した方が無難。推定で保管しようとすると大分ズレる危険がある。 - 欠損値は、ランダムに発生しているか、パターンがあるか?
MICE(連鎖方程式による多重代入法)とは:
- Multiple Imputations by Chained Equationsの略
- 数学的詳細は、pdf(連鎖方程式による多重代入法)参照
利用ライブラリ:
from sklearn.experimental import enable_iterative_imputer # ※このライブラリも必要
from sklearn.impute import IterativeImputer
https://scikit-learn.org/stable/modules/generated/sklearn.impute.IterativeImputer.html
手順:
- 欠損値を除いたカテゴリカル変数を順序変数に数値化
- IterativeImputer()インスタンスで欠損値埋める
- データフレームに反映する
コード例:
※ 下記例では、訓練データとテストデータを合体したデータで欠損値を補完している。(なので、訓練データとテストデータどちらも一緒に補完している。
# 対象データ
# MICE imputation用に、categorical変数を数値化する
MICE_combined_data = combined_df.copy()
# Categoricalデータ(文字列)取り出し
Cat_data = MICE_combined_data[object_list]
・Cat_data の内容
# -- すべてのCategorcal変数を、欠損値のある状態でOrdinal Encodingする
# MICE imputation用に、categorical変数を数値化する
MICE_combined_data = combined_df.copy()
# Categoricalデータ(文字列)取り出し
Cat_data = MICE_combined_data[object_list]
# Ordinal Encodersインスタンス用の辞書作成
ordinal_enc_dict = {}
# -- 変数をすべてエンコーディング
for col_name in Cat_data:
# 変数毎のordinal encoderインスタンス作成
ordinal_enc_dict[col_name] = OrdinalEncoder()
# 欠損値以外のデータ取り出し
col = Cat_data[col_name]
col_not_null = col[col.notnull()]
reshaped_vals = col_not_null.values.reshape(-1, 1)
# 欠損値以外のデータをエンコーディング
encoded_vals = ordinal_enc_dict[col_name].fit_transform(reshaped_vals)
# カテゴリ値をエンコーディング結果と入れ替え
Cat_data.loc[col.notnull(), col_name] = np.squeeze(encoded_vals)
# dfに反映
MICE_combined_data[object_list] = Cat_data
# -- MICEで欠損値の補完(全データを渡すことで、欠損値が全て埋まる)
# MICEで欠損値補完
from sklearn.experimental import enable_iterative_imputer # ※このライブラリも必要
from sklearn.impute import IterativeImputer
MICE_imputer = IterativeImputer(max_iter=200)
# 上記のmax_iterのデフォルトは10だが、このサイトによるとモンテカルロ法による推定のため、200ぐらいはイテレーションをした方が良いらしい!!!
MICE_imputed_data = MICE_imputer.fit_transform(MICE_combined_data)
# ※カテゴリカル変数に補完する時は、整数を入れたいのでfit_transformの結果をnp.round()で丸めた値を使う。-> 補 参照
# dfに反映
MICE_combined_data.iloc[:,:] = MICE_imputed_data
補:np.round()で整数にして補完する場合
MICE_imputed_data = pd.DataFrame(np.round(MICE_imputer.fit_transform(MICE_combined_data)), columns=MICE_combined_data.columns)
欠損値補完状況の確認
ヒストグラムで補完前後の分布状況を確認
g = sns.kdeplot(combined_df['LotFrontage'], color='Red', shade=True)
g = sns.kdeplot(MICE_combined_data['LotFrontage'], color='Blue', shade=True)
g.set_xlabel('LotFrontage')
g.set_ylabel('Frequency')
g.set_title('imputation by MICE')
g = g.legend(['before imputation', 'after imputation'])
ちなみに、最頻値で補完した結果が以下のグラフ。
g2 = sns.kdeplot(combined_df['LotFrontage'], color='Red', shade=True)
g2 = sns.kdeplot(MeMo_combined_data['LotFrontage'], color='Blue', shade=True)
g2.set_xlabel('LotFrontage')
g2.set_ylabel('Frequency')
g2.set_title('imputation by Mode')
g2 = g2.legend(['before imputation', 'after imputation'])
最頻値で補完した方は、最頻値の頻度がおおきくなってしまっている。
KNNによる欠損値補完
利用ライブラリ
from sklearn.impute import KNNImputer
※1 kの数など、パラメーターが複数有るが、そのへんはマニュアル参照
※2 kの数を適切に設定しないと、いい具合に補完できない。kaggleの住宅価格予想で使ってみたら、中央値・最頻値で補完したものよりスコアが悪かった・・・。kの数の設定は色々試す必要があるので、MICE選んでた方がいいかのかもしれない。
コード例)
KNN_combined_dataは、pandas.DataFrameでカテゴリカル変数は数値変換済み。
# KNNで欠損値補完
KNN_imputer = KNNImputer() # デフォルトのkの数は5
KNN_imputed_data = KNN_imputer.fit_transform(KNN_combined_data)
0コメント