【Pandas】データフレームの欠損値を埋める方法を解説

集めたデータを分析しようと中身を見てみると欠損が所々に、、、

といったように、生のデータがすぐ分析に使える状態でないことは多々あります。データに欠損があると、分析における様々な処理に支障がでます。

欠損があるときは、そのデータ項目を削除したり、ルールを決めて欠損値を補完する場合が多いです。

今回は、Pandasのデータフレームで欠損値を補完する方法を紹介していきます。

使用するデータフレーム

今回は以下のデータフレームをサンプルに使用します。

import pandas as pd

df = pd.DataFrame(
    data={"A":[1,3,None,None,None,11],
          "B":["イヌ", "ネコ", "サル", None, "ウサギ", None],
          "C":["a", None, "c", "d", "e", "f"],
          "D":[None,None,None,None,None,None]})
欠損のあるデータフレーム

いたるところに欠損を確認できます。

*nanとNoneが欠損です。(nanはnumpy.Nan)

データフレームの欠損を補完する手法

データフレームの欠損を補完するメソッドは、主にfillna()を用います。引数を操作することで、ルールに則った補完ができます。

以下に、様々な補完方法をまとめます。

全ての欠損を同じ値で補完

すべての欠損を同じ値で補完する場合は、fillna()の引数に数値や文字列を渡します。

引数に0を渡すと、すべての欠損が0に置換されます。

df1 = df.copy()
#すべての欠損値を0で置換
df1 = df1.fillna(0)
欠損が0で置換されたデータフレーム

文字列で補完することもできます。

df1 = df1.fillna("ゾウ")
欠損が”ゾウ”で置換されたデータフレーム

列ごとに値を指定して補完

辞書で値を指定して補完

fillna()に辞書 {列名 : 補完したい値}を渡すことで、列ごとに指定した値で欠損を置換することができます。

df2 = df.copy()
#列ごとに値を指定して置換(辞書)
df2 = df2.fillna({"A":100, "B":"ライオン", "C":"b", "D":1})
列ごとに指定した値で欠損を置換(辞書)

Seriesで値を指定して補完

列ごとに置換したい値をSeriesで指定することもできます。

#列ごとに値を指定して置換(Series)
fill_series = pd.Series([100, "ゾウ", "z", 50], index=["A", "B", "C", "D"])
df2 = df2.fillna(fill_series)

Seriesはインデックスが列名、値には置換したい値が入ります。

Seriesの中身

置換結果は以下のようになります。

列ごとに指定した値で欠損を置換(Series)

統計量で補完

データフレームの統計量をfillna()に渡すと、その統計量で欠損を置換することができます。ただし、置換できるのは数値型の列に限られます。

今回紹介する統計量以外(標準偏差等)でももちろん置換可能です。

平均値で補完

df3 = df.copy()
#各列の平均値で置換
df3 = df3.fillna(df.mean())
平均値で欠損を置換

最大値で補完

#最大値で置換
df3 = df3.fillna(df.max())
最大値で欠損を置換

前後の値で補完

欠損の前後の値で補完することもできます。前後の値で補完する場合は、fillna()の引数methodを指定します。

前の値で補完

前の値で欠損を補完する場合は、methodに”ffill”を指定します。

df4 = df.copy()
#前の値で置換
df4 = df4.fillna(method='ffill')
前の値で欠損を補完

D列のように先頭行から欠損が続く場合は補完できません。

後ろの値で補完

後ろの値で欠損を補完する場合はmethodに”bfill”を指定します。

#後ろの値で置換
df4 = df4.fillna(method='bfill')
後ろの値で欠損を補完

D列のように最後行から欠損が続く場合は補完できません。

線形補完

これまでは同一列では全て同じ値で置換をしていましたが、欠損の前後の値を線形につなぐような補完もできます。

欠損の線形補完にはinterpolate()を用います。

df5 = df.copy()
#線形補完
df5 = df5.interpolate()
欠損を線形補完

A列を見ると、欠損の前後の値を線形に補完するような値に置換されています。この方法は、数値型以外の列や全て欠損の列には適用できません。

線形補完にならない場合

また、数値型の列でも、欠損の前に数値がない場合や後ろに数値がない場合は線形補完されません(当たり前ですが)。欠損の前に値がない場合はffill、後ろに値がない場合はbfillでの置換と同様の結果が得られます。以下の例(A列)は欠損の後ろに値存在しないため、線形補完ではなくffillと同様の結果が得られます。

df = pd.DataFrame(
    data={"A":[1,3,None,None,None,None],
          "B":["イヌ", "ネコ", "サル", None, "ウサギ", None],
          "C":["a", None, "c", "d", "e", "f"],
          "D":[None,None,None,None,None,None]})
欠損の後ろに値がない(A列)場合
df = df.interpolate()
ffillと同じ結果が得られる

Pythonでデータサイエンスするなら

Pythonでデータサイエンスをするなら、以下の書籍がおすすめです。Pandas、matplotlib、Numpy、scikit-learnといったデータサイエンスに必要なライブラリを、体系立てて一通り学ぶことができます。

ややお値段高めですが、これ1冊で十分という内容・ボリュームなので、損はしないと思います^^

初学者の方にはこちらもオススメです^^

まとめ

データフレームの欠損を補完する方法を紹介しました。どのように欠損を埋めるかは、そのときのデータの特徴に応じて判断する必要があります。

様々な方法で欠損処理ができるので、その時々に応じてデータの前処理を行ってください。

ではでは👋