データ分析の現場において、欠損値(NaN)の扱いは避けて通れない重要な課題です。
特に時系列データや連続性のある観測データでは、欠損した箇所を単純に削除するのではなく、その前後の値を使って補完することが一般的です。
Pythonのデータ解析ライブラリであるPandasには、これらの欠損値を効率的に処理するための強力なメソッドが備わっています。
本記事では、fillnaメソッドの基本的な使い方から、最新のPandasで推奨されているffillおよびbfillによる補完手法について詳しく紹介します。
データの整合性を保ちながら欠損値を処理するテクニックを身につけ、分析の精度を向上させましょう。
Pandasにおける欠損値補完の基本
Pandasでは、欠損値は主にNaN(Not a Number)として表されます。
欠損値を処理する際、平均値や中央値で埋める方法もありますが、データの並びに意味がある場合は前後の有効な値を利用する手法が非常に有効です。
従来はfillna(method='ffill')といった記述が主流でしたが、最新のPandas(バージョン2.0以降および3.0系)では、より直感的な専用メソッドの使用が推奨されています。
まずは、今回使用するサンプルデータを作成して、挙動を確認する準備をしましょう。
import pandas as pd
import numpy as np
# サンプルデータの作成
df = pd.DataFrame({
'date': pd.date_range('2026-01-01', periods=6),
'sales': [100, np.nan, np.nan, 400, np.nan, 600]
})
print(df)
date sales
0 2026-01-01 100.0
1 2026-01-02 NaN
2 2026-01-03 NaN
3 2026-01-04 400.0
4 2026-01-05 NaN
5 2026-01-06 600.0
ffillメソッドによる前方補完
ffillは「forward fill」の略で、欠損値を直前の有効な値で埋める方法です。
ffillの基本的な使い方
時系列データにおいて、ある時点の値が次の観測まで維持されると仮定できる場合に適しています。
例えば、在庫数や設定値など、変化があったときだけ記録されるデータに有効です。
# ffillメソッドで前方補完
df_ffilled = df.ffill()
print(df_ffilled)
date sales
0 2026-01-01 100.0
1 2026-01-02 100.0
2 2026-01-03 100.0
3 2026-01-04 400.0
4 2026-01-05 400.0
5 2026-01-06 600.0
上記の実行結果を見ると、インデックス1と2の欠損値が、その直前であるインデックス0の値(100.0)で埋められていることがわかります。
bfillメソッドによる後方補完
bfillは「backward fill」の略で、欠損値を直後の有効な値で埋める方法です。
bfillの基本的な使い方
将来発生するイベントの値を遡って適用したい場合や、データの性質上、後ろの値に近いことが予想される場合に使用します。
# bfillメソッドで後方補完
df_bfilled = df.bfill()
print(df_bfilled)
date sales
0 2026-01-01 100.0
1 2026-01-02 400.0
2 2026-01-03 400.0
3 2026-01-04 400.0
4 2026-01-05 600.0
5 2026-01-06 600.0
実行結果では、インデックス1と2の欠損値が、直後に位置するインデックス3の値(400.0)で補完されています。
fillnaメソッドでの代替指定
以前のPandasでは、fillna()メソッドの引数にmethod='ffill'やmethod='bfill'を指定することが一般的でした。
しかし、最新のライブラリ環境ではこれらの引数は非推奨(FutureWarning)となっており、専用のメソッドを使うことが推奨されています。
もし古いコードをメンテナンスする場合は、以下の対応表を参考に書き換えを検討してください。
| 旧来の書き方(非推奨) | 現在の推奨される書き方 |
|---|---|
df.fillna(method='ffill') | df.ffill() |
df.fillna(method='bfill') | df.bfill() |
専用メソッドを使用することで、コードの可読性が高まり、将来的な仕様変更によるバグも防ぐことができます。
補完の範囲を制限するlimitパラメータ
実務では、連続する欠損値をすべて埋めるのではなく、一定の範囲内だけに限定して補完したいケースがあります。
例えば、1日分の欠損なら前の値で埋めても良いが、3日以上連続して欠損している場合は信頼性が低いため埋めたくない、といった場合です。
このような時には、limitパラメータを使用します。
# 連続する欠損値を最大1つまで補完
df_limited = df.ffill(limit=1)
print(df_limited)
date sales
0 2026-01-01 100.0
1 2026-01-02 100.0
2 2026-01-03 NaN
3 2026-01-04 400.0
4 2026-01-05 400.0
5 2026-01-06 600.0
この結果では、インデックス1は補完されていますが、連続する2つ目の欠損値であるインデックス2はNaNのまま保持されています。
これにより、過剰なデータの推定を抑制し、分析の精度を担保することができます。
軸方向を指定した補完(axis)
ここまでは行方向(垂直方向)の補完を見てきましたが、DataFrameの列方向(水平方向)で値を引き継ぎたい場合もあります。
その場合は、axisパラメータを指定します。
デフォルトはaxis=0(またはaxis='index')ですが、axis=1(またはaxis='columns')に設定することで横方向の補完が可能です。
# 横方向(列間)での補完用データ
df_wide = pd.DataFrame({
'A': [10, np.nan, 30],
'B': [np.nan, 50, np.nan]
})
# 横方向に前方補完
df_row_filled = df_wide.ffill(axis=1)
print(df_row_filled)
A B
0 10.0 10.0
1 NaN 50.0
2 30.0 30.0
列Aにある値が列Bの欠損値にコピーされていることが確認できます。
時系列データでの実戦的な活用例
ffillやbfillが最も活躍するのは、株価やセンサーログなどの時系列データです。
特定の時刻にデータが取得できなかった際、前後の文脈を考慮した補完を行うことで、機械学習モデルの学習データとして利用可能な形に整えることができます。
ただし、時系列データの分析(特に予測モデル)においてbfillを使用する際は注意が必要です。
なぜなら、未来の値を過去の欠損補完に使うことで「カンニング(データリーク)」が発生するリスクがあるからです。
予測タスクにおいては、基本的にはffillのみを使用し、過去の情報だけに基づいて補完を行うのが鉄則です。
まとめ
Pandasを用いた欠損値補完は、データの品質を高めるための不可欠なプロセスです。
今回紹介したffillとbfillを使い分けることで、データの並び順に応じた適切な穴埋めが可能になります。
最後に、主要なポイントを整理します。
- 直前の値で埋める場合はffillを使用する。
- 直後の値で埋める場合はbfillを使用する。
fillna(method=...)は非推奨であるため、専用メソッドへの移行が必要である。limit引数を活用して、過度な補完を防ぐ。- 時系列データの予測では、未来の値を使う
bfillの扱いに注意する。
適切な手法を選択し、ノイズの少ない綺麗なデータセットを構築していきましょう。
