【Pandas徹底攻略】欠損値NaNを賢く埋める!fillnaでデータクレンジング


 

データ分析において、欠損値(NaN)は避けて通れない課題です。特に機械学習モデルの構築や正確な統計分析を行うためには、これらの欠損値を適切に処理する必要があります。Pandasの**fillnaメソッド**は、欠損値を柔軟かつ効率的に別の値で「穴埋め」(置換)するための強力なツールです。この記事では、fillnaの基本的な使い方から、データ分析の現場でよく使われる応用例まで、短いサンプルコードと丁寧な解説を交えてご紹介します。


 

fillnaメソッドとは?なぜ欠損値を埋めるのか?

 

fillnaメソッドは、PandasのDataFrameやSeriesに存在する欠損値(NaN, None, pd.NAなど)を指定した値や方法で置き換えるために使用されます。欠損値を埋める主な目的は以下の通りです。

  • 分析の続行: 多くの分析手法や機械学習アルゴリズムは欠損値を扱えないため、事前に埋める必要があります。

  • データの損失回避: 欠損値を含む行や列を安易に削除すると、貴重な情報まで失ってしまう可能性があります。

  • モデル性能の向上: 適切な値で欠損値を補完することで、機械学習モデルの精度が向上することがあります。


 

fillnaの基本的な使い方

 

まずは、fillnaメソッドの最も基本的な使い方を見ていきましょう。

 

固定値で欠損値を埋める

 

最もシンプルな方法として、すべての欠損値を特定の固定値で置き換えることができます。

Python
 
import pandas as pd
import numpy as np

# サンプルDataFrameの作成
df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': ['apple', np.nan, 'orange', 'grape'],
    'C': [10, 20, 30, np.nan]
})
print("オリジナルDataFrame:\n", df)

# すべてのNaNを0で埋める
df_filled_zero = df.fillna(0)
print("\nNaNを0で埋めた後:\n", df_filled_zero)

解説:

DataFrame内のすべてのnp.nanが0に置換されました。ただし、文字列型の列に数値を埋めると不自然になる場合があるので注意が必要です。


 

fillnaの応用的な使い方

 

fillnaメソッドは、固定値で埋める以外にも、より高度な方法で欠損値を補完する機能を持っています。

 

前の行/次の行の値で埋める(伝播補完)

 

時系列データなど、順序に意味があるデータでよく使われる補完方法です。

 

前の行の値で埋める: method='ffill' (forward fill)

 

method='ffill'(またはmethod='pad')を指定すると、欠損値の直前の有効な値で埋めます。

Python
 
# 前の行の値で埋める (ffill)
df_ffill = df.fillna(method='ffill')
print("\n前の行の値で埋めた後 (ffill):\n", df_ffill)

解説:

例えば、’A’列のインデックス2のnp.nanは、その前の有効な値である2で埋められています。

 

次の行の値で埋める: method='bfill' (backward fill)

 

method='bfill'(またはmethod='backfill')を指定すると、欠損値の直後の有効な値で埋めます。

Python
 
# 次の行の値で埋める (bfill)
df_bfill = df.fillna(method='bfill')
print("\n次の行の値で埋めた後 (bfill):\n", df_bfill)

解説:

‘B’列のインデックス1のnp.nanは、その次の有効な値である’orange’で埋められています。


 

統計量で欠損値を埋める

 

数値データの場合、その列の平均値、中央値、最頻値などで欠損値を補完するのは非常に一般的な手法です。

 

平均値で埋める

 

Python
 
# 'A'列のNaNを'A'列の平均値で埋める
df_mean_fill = df.copy() # オリジナルを保持するためにコピー
mean_a = df_mean_fill['A'].mean()
df_mean_fill['A'] = df_mean_fill['A'].fillna(mean_a)
print("\n'A'列を平均値で埋めた後:\n", df_mean_fill)

解説:

df_mean_fill[‘A’].mean()で’A’列の平均値を計算し、その値で’A’列のNaNを埋めています。

 

中央値で埋める

 

Python
 
# 'C'列のNaNを'C'列の中央値で埋める
df_median_fill = df.copy()
median_c = df_median_fill['C'].median()
df_median_fill['C'] = df_median_fill['C'].fillna(median_c)
print("\n'C'列を中央値で埋めた後:\n", df_median_fill)

解説:

外れ値の影響を受けにくい中央値で補完したい場合に有効です。


 

特定の列ごとに異なる値で埋める

 

DataFrame全体ではなく、列ごとに異なる値で欠損値を埋めたい場合は、辞書形式で指定します。

Python
 
# 列ごとに異なる値で埋める
fill_values = {'A': df['A'].mean(), 'B': 'Unknown', 'C': 0}
df_col_specific_fill = df.fillna(fill_values)
print("\n列ごとに異なる値で埋めた後:\n", df_col_specific_fill)

解説:

‘A’列は平均値、’B’列は’Unknown’、’C’列は0でそれぞれNaNが埋められています。これにより、データ型に応じた柔軟な補完が可能です。


 

注意点: inplace引数

 

fillnaメソッドはデフォルトで、新しいDataFrameまたはSeriesを返します。元のオブジェクトを直接変更したい場合は、inplace=Trueを設定します。

Python
 
# 例: inplace=Trueの使用(非推奨とされることが多い)
df_inplace = pd.DataFrame({'D': [1, np.nan]})
print("inplace適用前DataFrame:\n", df_inplace)

df_inplace.fillna(99, inplace=True)
print("\ninplace適用後DataFrame:\n", df_inplace)

解説:

inplace=Trueはメモリ効率が良いですが、元のデータを上書きしてしまうため、予期せぬ挙動につながる可能性があります。通常は、df_filled = df.fillna(…)のように、新しい変数に代入する方が安全で推奨される方法です。


 

まとめ

 

Pandasのfillnaメソッドは、DataFrameやSeriesの欠損値(NaN)を補完するための非常に強力で柔軟な機能です。固定値での置換から、前後の値による伝播補完、統計量による補完、さらには列ごとの補完まで、様々なシナリオに対応できます。これらのfillnaのテクニックをマスターすることで、データの前処理が格段に効率的になり、より信頼性の高い分析結果を得られるようになるでしょう。