この記事について
Scikit-learnのSimpleImputerクラスを使用すると、データセットの欠損値を簡単に補完することができます。Kaggleの練習用Competitionでも使われているタイタニックのデータセットを例に、SimpleImputerをどのように使うか見ていきたいと思います。
データセット
タイタニックデータセットのロード
今回は seaboarn を使用してタイタニックのデータセットをロードします。
import seaborn as sns df = sns.load_dataset("titanic") print(df.head())
survived pclass sex age ... deck embark_town alive alone 0 0 3 male 22.0 ... NaN Southampton no False 1 1 1 female 38.0 ... C Cherbourg yes False 2 1 3 female 26.0 ... NaN Southampton yes True 3 1 1 female 35.0 ... C Southampton yes False 4 0 3 male 35.0 ... NaN Southampton no True [5 rows x 15 columns]
このように df
にはタイタニックの乗客の年齢、性別といったデータが格納された状態になります。
欠損値の状況を確認する
info()
を使って各列の欠損値の状況を確認してみます。
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 891 entries, 0 to 890 Data columns (total 15 columns): survived 891 non-null int64 pclass 891 non-null int64 sex 891 non-null object age 714 non-null float64 sibsp 891 non-null int64 parch 891 non-null int64 fare 891 non-null float64 embarked 889 non-null object class 891 non-null category who 891 non-null object adult_male 891 non-null bool deck 203 non-null category embark_town 889 non-null object alive 891 non-null object alone 891 non-null bool dtypes: bool(2), category(2), float64(2), int64(4), object(5) memory usage: 80.6+ KB
データのサンプル数は891で、age
, embarked
, embark_town
, deck
の4列に欠損値があることがわかります。下記コードで具体的な欠損値の個数もわかります。
df.isna().sum()
survived 0 pclass 0 sex 0 age 177 sibsp 0 parch 0 fare 0 embarked 2 class 0 who 0 adult_male 0 deck 688 embark_town 2 alive 0 alone 0 dtype: int64
年齢データが欠損しているサンプル
年齢カラムに入っているデータの概要を見てみます。
df.age.describe()
count 714.000000 mean 29.699118 std 14.526497 min 0.420000 25% 20.125000 50% 28.000000 75% 38.000000 max 80.000000 Name: age, dtype: float64
平均が29.69、中央値が28で、最年少が0.42歳、最高齢が80歳というデータのようです。
年齢が欠損しているサンプルは下記のようにして取り出せます。
print(df[df.age.isna()].head())
survived pclass sex age ... deck embark_town alive alone 5 0 3 male NaN ... NaN Queenstown no True 17 1 2 male NaN ... NaN Southampton yes True 19 1 3 female NaN ... NaN Cherbourg yes True 26 0 3 male NaN ... NaN Cherbourg no True 28 1 3 female NaN ... NaN Queenstown yes True [5 rows x 15 columns]
欠損値の補完
平均値での補完
では実際に年齢の補完をしてみます。SimpleImputerクラスではstrategyという引数を指定できます。これは欠損値を補完する方法を指定するもので、平均値 (mean)、中央値 (median)、最頻値 (most_frequent)、定数 (constant) の4つの中からしていできます。例えば、年齢を平均値で補完する場合は下記のようなコードになります。
from sklearn.impute import SimpleImputer mean_imputer = SimpleImputer(strategy='mean') mean_imputed_df = df.copy() mean_imputed_df[['age']] = mean_imputer.fit_transform(mean_imputed_df[['age']]) print(mean_imputed_df[df.age.isna()].head())
survived pclass sex age ... deck embark_town alive alone 5 0 3 male 29.699118 ... NaN Queenstown no True 17 1 2 male 29.699118 ... NaN Southampton yes True 19 1 3 female 29.699118 ... NaN Cherbourg yes True 26 0 3 male 29.699118 ... NaN Cherbourg no True 28 1 3 female 29.699118 ... NaN Queenstown yes True [5 rows x 15 columns]
ageがNaNだったサンプルも、すべて平均値の29.69...という値で補完されている様子が確認できます。
中央値での補完
中央値や最頻値の場合も同様です。試しに中央値でも年齢を補完してみると下記のようになります。
median_imputer = SimpleImputer(strategy='median') median_imputed_df = df.copy() median_imputed_df[['age']] = median_imputer.fit_transform(median_imputed_df[['age']]) print(median_imputed_df[df.age.isna()].head())
survived pclass sex age ... deck embark_town alive alone 5 0 3 male 28.0 ... NaN Queenstown no True 17 1 2 male 28.0 ... NaN Southampton yes True 19 1 3 female 28.0 ... NaN Cherbourg yes True 26 0 3 male 28.0 ... NaN Cherbourg no True 28 1 3 female 28.0 ... NaN Queenstown yes True [5 rows x 15 columns]
今度はageの列が中央値である28.0で補完されているようすが確認できます。
カテゴリ変数の補完
これまでは年齢という数値に対しての補完でしたが、カテゴリ変数に対する補完も同様に行うことができます。例えば embark_town
という乗船した街を表す変数の欠損は2サンプルありました。乗船場所は3種類しか存在しないようで、891人中644人はSouthamptonという街から乗船しているようです。
df.embark_town.describe()
count 889 unique 3 top Southampton freq 644 Name: embark_town, dtype: object
embark_townが欠損している人のデータは下記で参照できます。確かに2名分しか欠損データがないようです。
print(df[df.embark_town.isna()].head())
survived pclass sex age ... deck embark_town alive alone 61 1 1 female 38.0 ... B NaN yes True 829 1 1 female 62.0 ... B NaN yes True [2 rows x 15 columns]
カテゴリ変数である embark_town も SimpleImputerを使って補完することができます。カテゴリ変数には平均値や中央値は存在しないので、最頻値か定数を指定してあげる必要があります。今回は最頻値をしていしてみます。
most_frequent_imputer = SimpleImputer(strategy='most_frequent') embark_town_imputed_df = df.copy() embark_town_imputed_df['embark_town'] = most_frequent_imputer.fit_transform(embark_town_imputed_df[['embark_town']]) print(embark_town_imputed_df[df.embark_town.isna()].head())
survived pclass sex age ... deck embark_town alive alone 61 1 1 female 38.0 ... B Southampton yes True 829 1 1 female 62.0 ... B Southampton yes True [2 rows x 15 columns]
確かに、embark_townの列が最頻値であるSouthamptonで補完されているようです。