データ分析において、欠損値(NaN/None)の処理は避けて通れない前処理のひとつです。データに欠損があると、集計や機械学習の処理に支障が出るため、適切な方法で補完する必要があります。
この記事では、Pandasのデータフレームで欠損値を補完するさまざまな方法を紹介します。
Pandasバージョン
本記事は、Pandas 2.2.3の情報を基に執筆しています。
import pandas as pd
print(pd.__version__)
>>
2.2.3使用するデータフレーム
今回は以下の欠損値(NaNおよびNone)を含むデータフレームをサンプルとして使用します。
import pandas as pd
df = pd.DataFrame(
data={"A":[1,3,None,None,None,11],
"B":["dog", "cat", "monkey", None, "rabbit", None],
"C":["a", None, "c", "d", "e", "f"],
"D":[None,None,None,None,None,None]})
>>
A B C D
0 1.0 dog a None
1 3.0 cat None None
2 NaN monkey c None
3 NaN None d None
4 NaN rabbit e None
5 11.0 None f Noneデータフレームの欠損を補完する手法
データフレームの欠損値を補完するには、主にfillna()メソッドを使用します。引数の指定方法を変えることで、さまざまなルールに基づいた補完が可能です。
全ての欠損を同じ値で補完
すべての欠損値を同一の値で補完する場合は、fillna()の引数に値を直接渡します。
df1 = df.copy()
# すべての欠損値を0で置換
df1 = df1.fillna(0)
>>
A B C D
0 1.0 dog a 0
1 3.0 cat 0 0
2 0.0 monkey c 0
3 0.0 0 d 0
4 0.0 rabbit e 0
5 11.0 0 f 0文字列で補完することも可能です。
df1 = df1.fillna("elephant")
>>
A B C D
0 1.0 dog a elephant
1 3.0 cat elephant elephant
2 elephant monkey c elephant
3 elephant elephant d elephant
4 elephant rabbit e elephant
5 11.0 elephant f elephant列ごとに値を指定して補完
辞書で値を指定
fillna()に辞書{列名: 補完値}を渡すことで、列ごとに異なる値で補完できます。
df2 = df.copy()
# 列ごとに値を指定して置換(辞書)
df2 = df2.fillna({"A":"lion", "B":"lion", "C":"b", "D":"b"})
>>
A B C D
0 1.0 dog a b
1 3.0 cat b b
2 lion monkey c b
3 lion lion d b
4 lion rabbit e b
5 11.0 lion f b列ごとに異なる型で補完することも可能ですが、今後のバージョンで非推奨となる見込みです。
df2 = df.copy()
df2 = df2.fillna({"A":10, "B":"lion", "C":"b", "D":5})
>>
A B C D
0 1.0 dog a 5
1 3.0 cat b 5
2 10.0 monkey c 5
3 10.0 lion d 5
4 10.0 rabbit e 5
5 11.0 lion f 5
FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version.Seriesで値を指定
Series形式で列ごとの補完値を指定することもできます。Seriesのインデックスが列名に対応します。
fill_series = pd.Series(["lion", "lion", "z", "z"], index=["A", "B", "C", "D"])
>>
A lion
B lion
C z
D z
dtype: object作成したSeriesをfillna()の引数として渡します。
df2 = df.copy()
df2 = df2.fillna(fill_series)
>>
A B C D
0 1.0 dog a z
1 3.0 cat z z
2 lion monkey c z
3 lion lion d z
4 lion rabbit e z
5 11.0 lion f z統計量で補完
データフレームの統計量をfillna()に渡すことで、各列の統計量に基づいた補完が可能です。ただし、この方法は数値型の列にのみ有効です。
平均値で補完
df3 = df.copy()
# 各列の平均値で置換
df3 = df3.fillna(df.mean(numeric_only=True))
>>
A B C D
0 1.0 dog a None
1 3.0 cat None None
2 5.0 monkey c None
3 5.0 None d None
4 5.0 rabbit e None
5 11.0 None f None最大値で補完
df3 = df.copy()
# 各列の最大値で置換
df3 = df3.fillna(df.max(numeric_only=True))
>>
A B C D
0 1.0 dog a None
1 3.0 cat None None
2 11.0 monkey c None
3 11.0 None d None
4 11.0 rabbit e None
5 11.0 None f None上記以外にも、
median()(中央値)やstd()(標準偏差)など、任意の統計量で補完できます。
前後の値で補完
欠損値の前後にある値で補完する方法です。この場合はfillna()ではなく、専用のffill()およびbfill()メソッドを使用します。
注意:
fillna(method="ffill")のようにmethodパラメータで指定する方法は非推奨となっており、将来のバージョンで削除される予定です。
前の値で補完(ffill)
前方の値で欠損を補完する場合はffill()を使用します。D列のように先頭行から欠損が連続する場合は補完できません。
df4 = df.copy()
# 前の値で置換
df4 = df4.ffill()
>>
A B C D
0 1.0 dog a None
1 3.0 cat a None
2 3.0 monkey c None
3 3.0 monkey d None
4 3.0 rabbit e None
5 11.0 rabbit f None後ろの値で補完(bfill)
後方の値で欠損を補完する場合はbfill()を使用します。D列のように末尾まで欠損が続く場合は補完できません。
df4 = df.copy()
# 後ろの値で置換
df4 = df4.bfill()
>>
A B C D
0 1.0 dog a None
1 3.0 cat c None
2 11.0 monkey c None
3 11.0 rabbit d None
4 11.0 rabbit e None
5 11.0 None f None線形補間
欠損値の前後の値を直線で結ぶように値を補間する方法です。interpolate()メソッドを使用します。
df5 = df.copy()
# 線形補間
df5 = df5.interpolate()
>>
A B C D
0 1.0 dog a None
1 3.0 cat None None
2 5.0 monkey c None
3 7.0 None d None
4 9.0 rabbit e None
5 11.0 None f NoneA列を見ると、欠損の前後の値(3.0と11.0)を等間隔で補間した値(5.0, 7.0, 9.0)に置換されています。
注意:
interpolate()は数値型の列にのみ有効です。文字列型の列や全欠損の列には適用されません。
線形補間ができない場合
数値型の列であっても、欠損の前後どちらか一方に値が存在しない場合は線形補間が適用されません。
- 欠損の前に値がない場合: 補間されない(NaNのまま)
- 欠損の後ろに値がない場合: 前方の値で補完される(ffillと同等の結果)
df = pd.DataFrame(
data={"A":[1,3,None,None,None,None],
"B":["dog", "cat", "monkey", None, "rabbit", None],
"C":["a", None, "c", "d", "e", "f"],
"D":[None,None,None,None,None,None]})df = df.interpolate()
>>
A B C D
0 1.0 dog a None
1 3.0 cat None None
2 3.0 monkey c None
3 3.0 None d None
4 3.0 rabbit e None
5 3.0 None f Noneまとめ
今回は、Pandasでデータフレームの欠損値を補完するさまざまな方法を紹介しました。
fillna(): 固定値、辞書、Series、統計量による補完ffill()/bfill(): 前方・後方の値による補完interpolate(): 前後の値を用いた線形補間
どの方法を使用するかは、データの性質や分析の目的によって異なります。例えば、時系列データでは前方補完(ffill)、数値データの平滑化には線形補間(interpolate)が有効なケースが多いです。データの特性を十分に理解した上で、適切な補完方法を選択してください。