データ分析を行うにあたって必要となってくるデータ前処理の方法ですが、PythonのPandasを使った欠損値を補完する方法を今回ご紹介できたらと思います。
本記事ではお手元のJupyter notebookでPythonとPandasが動く前提で紹介をしてきますが、Google Colaboratory を用いても検証できるため、是非試してみてください。

Pandasで欠損値(NaN)を処理する方法
利用するデータ
はじめに利用するデータですが、Kaggleで有名なタイタニック号の生存予測問題でよく利用されているデータセットをつかってきます。
Titanic: Machine Learning from Disaster
上記ページからzipファイルをダウンロードしローカル環境に展開してください。zipファイルを回答すると下記ファイルが入ってます。
今回はこの中のtrain.csvを利用して欠損値(NaN)を埋めてきます。私のGithubからもダウンロードできますので、どちらかでダウンロードしてください。
Pandasでデータの読み込み
まずはpandasの読み込みとread_csvでタイタニックのtrain.csvを読み込んできます。train.csvは任意の場所に配置いただき、相対パス・もしくは絶対パスで読み込んでください。
これでデータの読み込みは完了です。
欠損データを確認する方法
info() – データの要約をみる
それではPandasで読み込んだデータを見てきます。一番簡単な方法はinfo()
を使いデータの要約を見ていく方法です。
出力結果についてはPassengerId
カラムを例に左から
カラム名, 欠損していないデータ数, データ型
が表示されてます。データの最大値が[891]なので、それに満たないAge
(年齢)とCabin
(客室番号)とEmbarked
(出港地)が欠損していることがわかります。
isnull() – 欠損しているかレコード単位で確認する
infoではデータの要約を確認することができましたが、isnullでは各レコード単位に欠損値を確認することができます。
コメントアウトでも記載しておりますが、Trueが欠損している値でFalseが何らしらの値が入っていることをbooleanで示してます。
またisna()
関数でも同様のことができます。※isna()
関数はisnull()
のエイリアスになっており、呼び出し先は同じです。
head()は欠損値を処理する関数とは関係ないですが、上から5つレコードをとる処理になります。
isnull().sum()- データの欠損数を集計する
isnull()
にsum()
を使うと欠損値の集計が可能です。
infoとは逆で欠損値データが何個あるのか確認することができます。
欠損データを削除する方法(dropna)
欠損値しているデータを削除する場合dropna()
を使うことで削除することができます。削除方法については細かく設定ができますので紹介してきます。
またdropnaはレスポンスで削除を行うだけで、実際の格納先変数側は変更をしない仕様になっております。後述しますがinplace=True
を引数で用いることで変数に削除したレスポンスを反映することができます。
dropna() – 欠損している行,列ともに削除する
欠損している行と列を削除する場合は下記ようにdropna()
を引数なしで利用します。
行、列ともに削除されていることが出力結果で確認することができます。
dropna(how=, axis=) – 欠損している行,列ともに削除する
欠損している行と列を削除する際に引数を渡すことによって行のみ削除や列のみ削除、全部欠損している場合もしくは一部欠損している場合など細かく指定ができます。
コメントアウトでも記載しておりますが、axis
引数に削除したい軸を加えます。columns
or 1
であれば列を、rows
or 0
であれば行が削除されます。
また引数にhow
を用い、all
を指定すると全部欠損している場合のみ削除でき、any
を指定すると一部欠損している場合のみ削除することが可能です。
※デフォルトはany
になっております。
dropna(thresh=int) – 欠損していない項目が○○個未満あれば削除
dropnaでthresh
を用いると欠損している個数に応じて削除することができます。
タイタニックのデータは12カラム存在するため、欠損していない項目が10個未満であれば削除するように指定ができます。
dropna(inplace=True) – データの反映
引数にinplace=True
を用いることで変数に対して削除した変更を反映することができます。
copy()
はデータを簡単にコピーすることが可能になる関数です。=
でDataFrameを渡した場合、シンボリックリンクを行った時ような挙動になり、代入したDataFrame側の変更もコピー元に反映がされてしまいます。
欠損値を他の値で補填する方法(fillna)
欠損値しているデータを他の値で補填する方法としてfillna()
を使えば簡単に実装ができます。dropna同様にいくつかの引数が存在し、細かく設定することができますので紹介してきます。
fillna(int) – 固定の数値で補填する
fillnaの引数に、欠損値に埋めたい数値を入れることで、全ての欠損値が入れた値で補完されます。
先述したisnull()
で確認した通り、Cabin(客席番号)の値が1,3,5行目が欠損値しているため、fillna(0)
を使うことで0で補完することができました。
fillna(‘string’) – 固定の文字列で補填する
数値同様に文字列でも補填することができます。
欠損値に対して文字列で補填できていることが出力結果からもわかると思います。
fillna({‘col1’:int, ‘col2’: ‘str’}) – 列ごとに補填方法を変える
上記ではデータ全体に対しての補填方法をご紹介してきましたが、計算する時などのためにデータ型は統一したい等あると思いますので列ごとに補填内容を変更する方法をご紹介してきます。
引数はdict型を記述することで指定したカラムに対して補填することが可能です。
fillna(method=’ffill’) – 直前の値で埋める
fillna
の引数ffill
(forward fillの略)を指定することで直前の値で欠損値を補填することができます。
注意していただきたい点が先頭行については、もちろん直前の値が存在しないため、欠損値のままになります。
fillna(method=’bfill’) – 直後の値で埋める
ffill
との違いは直前ではなく、直後の値で欠損値を補填します。
ffill
同様に先頭行ではなく、最終行に欠損値があった場合、値は存在しないので補填されないことを留意してください。
fillna(limit=int) – 連続する欠損値を○○個まで補填する
あまりに欠損値が連続して続いているデータの場合、補填すること自体がノイズになりかねないため、いくつまで補填を行うのかlimit
引数を用いて指定することができます。
元データのinfo()
結果については先述しているので記載しておりませんが、幾分かの欠損値が補填されていることが確認できます。
fillna(df[‘col1’].mean()) – 平均値で欠損値を補填する
欠損値を埋める時に行う方法が数学関数を用いた補填になります。データの平均値で埋める場合は下記になります。
6行目のAge(年齢)カラムが欠損しているのですが、平均値で補填されていることが確認できます。
fillna(df[‘col1’].median()) – 中央値で欠損値を補填する
平均値同様に中央値で埋める方法を紹介してきます。
平均値と比べてもそんなにブレていないことがわかります。
fillna(df[‘col1’].mode().iloc[0]) – 最頻値で欠損値を補填する
最頻値で使うmode()
は平均値、中央値と処理が異なり、戻り値が複数存在する場合があります。その部分について後述してきます。
mode()
は扱う元データがDataFrame、Seriesよって戻り値が異なり、元データの型をそのまま戻り値として返してきます。
そのため、単一の変数ではないのでiloc[0]
を使って先頭の値を使ってあげる処理を加えております。iloc[0]
をつけないと補填されないため、注意してください。
まとめ
今回Pandasでの基本的な欠損値処理の方法をご紹介させていただきました。今後時間があればサンプルCSVを用いて具体的にどのように欠損値を埋め、データ分析をおこなっていくかについて記事にできたらと思っておます。
ここまで読んでいただきありがとうございました。
参照元
Pandasでnan値を削除、穴埋めするfillna、dropnaの使い方