データサイエンスや業務効率化の現場において、PythonのPandasライブラリは欠かせないツールとなっています。
しかし、実際のプロジェクトで扱うデータには、しばしば値が存在しない「欠損値(NaN)」が含まれています。
欠損値をそのまま放置すると、統計量の計算が狂ったり、機械学習モデルの学習時にエラーが発生したりする原因となります。
この記事では、Pandasで欠損値を効率的に埋めるための「fillna」メソッドの活用術を中心に、実務で役立つ具体的な手法を詳しく解説します。
2026年現在の最新のPandas仕様に基づいた、最適なデータクレンジングの手順を学んでいきましょう。
欠損値処理の重要性と基本的な考え方
データ分析の工程において、欠損値の扱いは分析の精度を左右する極めて重要なステップです。
欠損値が発生する理由は、アンケートの未回答やセンサーの故障、システムの不備など多岐にわたります。
これらの欠損値に対して、単に行を削除するだけでは、貴重なデータのサンプルサイズを減らしてしまうことになります。
そこで、適切な値で補完する(埋める)というアプローチが重要になります。
ただし、データの文脈を無視して適当な値で埋めると、分析結果に偏りが生じるリスクがあることも理解しておかなければなりません。
まずは、現在のデータフレーム内にどの程度の欠損値があるのかを確認する方法からおさらいしましょう。
欠損値の確認方法(isnull / isna)
Pandasでは、isnull()やisna()メソッドを使用して欠損値の有無を確認できます。
import pandas as pd
import numpy as np
# サンプルデータの作成
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [np.nan, 12, 13, 14],
'C': [21, np.nan, np.nan, 24]
})
# 各カラムごとの欠損値の数を確認
print(df.isnull().sum())
A 1
B 1
C 2
dtype: int64
このように、どの列にどれだけの欠損値があるかを把握することで、補完すべき優先順位や手法を検討する材料となります。
fillnaメソッドを用いた基本的な補完テクニック
Pandasで最も汎用的に使われるのがfillnaメソッドです。
このメソッドを使うことで、指定した値や特定のルールに従って欠損値を一括で置換することが可能です。
特定の定数で埋める
最もシンプルな方法は、欠損値を「0」や「欠損」といった特定の定数で埋めることです。
数値データであれば「0」、カテゴリデータであれば「Unknown」などの文字列で埋めることが一般的です。
# 欠損値をすべて0で埋める
df_zero = df.fillna(0)
print(df_zero)
A B C
0 1.0 0.0 21.0
1 2.0 12.0 0.0
2 0.0 13.0 0.0
3 4.0 14.0 24.0
特定のカラムのみを特定の値で埋めたい場合は、辞書形式で指定することもできます。
# カラムAは0、カラムCは-1で埋める
df_custom = df.fillna({'A': 0, 'C': -1})
print(df_custom)
代表値(平均値・中央値・最頻値)で埋める
統計的な観点から、データの分布を大きく崩さないために平均値や中央値で補完する手法がよく用いられます。
平均値は外れ値の影響を受けやすいため、データに極端な値が含まれる場合は中央値(median)の利用を検討してください。
# カラムAの欠損値を平均値で埋める
df['A'] = df['A'].fillna(df['A'].mean())
# カラムBの欠損値を中央値で埋める
df['B'] = df['B'].fillna(df['B'].median())
カテゴリ変数の場合は、最も頻繁に登場する値である「最頻値(mode)」を使用するのが定石です。
# 最頻値で埋める例(mode()はSeriesを返すため[0]で値を取得)
mode_val = df['C'].mode()[0]
df['C'] = df['C'].fillna(mode_val)
時系列データに最適な補完方法
時系列データの場合、前後の値には強い相関があることが多いため、単純な平均値よりも「直前の値」や「直後の値」で埋める方が自然です。
前の値で埋める (ffill) と後ろの値で埋める (bfill)
以前のPandasでは fillna(method='ffill') という書き方が一般的でしたが、最新バージョンでは ffill() メソッドや bfill() メソッドを直接呼び出すことが推奨されています。
- ffill (forward fill): 前にある有効な値を後ろにコピーします。
- bfill (backward fill): 後ろにある有効な値を前にコピーします。
# サンプルデータの再定義
df_time = pd.DataFrame({'Value': [10, np.nan, np.nan, 40]})
# 前の値で埋める
df_ffilled = df_time.ffill()
print(df_ffilled)
Value
0 10.0
1 10.0
2 10.0
3 40.0
株価データやセンサーログなど、時間の経過とともに変化するデータの補完にはこの手法が非常に有効です。
線形補間 (interpolate)
直前の値で固定するのではなく、前後の値から計算して滑らかに値を埋めたい場合には interpolate() を使用します。
例えば、10と40の間にある2つの欠損値を、線形的に20、30と埋めることができます。
# 線形補間を実行
df_interp = df_time.interpolate()
print(df_interp)
Value
0 10.0
1 20.0
2 30.0
3 40.0
応用:グループごとの統計量で欠損値を埋める
実務で非常に効果的なのが、特定のグループごとの平均値などで補完する手法です。
例えば「性別」と「身長」のデータがある場合、全体の平均身長で埋めるよりも、男女それぞれの平均身長で埋める方が正確です。
# サンプルデータ
df_group = pd.DataFrame({
'Category': ['A', 'A', 'B', 'B'],
'Value': [10, np.nan, 50, np.nan]
})
# カテゴリごとの平均値で補完
df_group['Value'] = df_group.groupby('Category')['Value'].transform(lambda x: x.fillna(x.mean()))
print(df_group)
transform メソッドを組み合わせることで、元のデータフレームのインデックスを維持したまま、グループ単位の統計量を適用できます。
2026年における最新の注意点
Pandasの進化に伴い、一部の引数や挙動が変更されています。
特に inplace=True の使用は、現在では非推奨(Deprecated)の流れにあります。
「元のデータを直接書き換えるのではなく、再代入を行う」という書き方が、将来的な互換性とコードの可読性の観点から推奨されています。
# 非推奨な書き方
df.fillna(0, inplace=True)
# 推奨される書き方
df = df.fillna(0)
また、大規模なデータセットを扱う場合は、メモリ効率を考慮して、補完後のデータ型(dtype)が意図せず float64 に変わっていないか注意を払う必要があります。
欠損値補完手法の使い分けまとめ
適切な手法を選択するための基準を、以下の表にまとめました。
| 手法 | 適用シーン | メリット |
|---|---|---|
| 定数(0など) | 欠損に意味がある場合 | 処理が速く、明確 |
| 平均値・中央値 | 正規分布に近い数値データ | 全体の統計量を維持しやすい |
| ffill / bfill | 時系列・継続データ | 時間の連続性を維持できる |
| interpolate | 滑らかな変化が必要なデータ | 前後関係を考慮した補間が可能 |
| Groupby補完 | 属性による差異が大きいデータ | 最も精度が高い補完が期待できる |
まとめ
Pandasの fillna をはじめとする欠損値処理メソッドは、データ分析の品質を支える基盤となります。
単にエラーを消すために埋めるのではなく、「なぜそのデータが欠損しているのか」を考察し、最適な補完アルゴリズムを選択することが重要です。
基本の定数補完から、時系列向けの ffill、さらには groupby を用いた高度な補完まで、状況に合わせて使い分けられるようになりましょう。
今回紹介した手法を活用して、より精度の高いデータ分析や機械学習モデルの開発に取り組んでください。
最新のPandasの仕様を常にチェックし、クリーンなコードで効率的なデータクレンジングを実現しましょう。
