【Pandas欠損値処理】NaNの除外・置換・抽出をマスターしてデータ分析の質を向上!🧹
データ分析を行う際、欠損値(Not a Number: NaN)の扱いは避けて通れない重要なステップです。データ収集の過程で欠損値が発生することはよくあり、これを適切に処理しないと、分析結果の信頼性が低下したり、エラーが発生したりする原因となります。
Pandasは、DataFrameやSeries内の欠損値を効率的に管理するための多彩な機能を提供しています。具体的には、欠損値を含む行や列を除外(削除)したり、特定の値で置換(穴埋め)したり、あるいは欠損値のある箇所を抽出したりするメソッドがあります。この記事では、これらの欠損値処理の主要なテクニックを、短いサンプルコードと丁寧な解説を交えてご紹介します。
欠損値(NaN)とは?なぜ処理が必要なのか?
**欠損値(NaN)**は、「Not a Number」の略で、数値として有効でないデータや、データが存在しないことを示す特殊な値です。Pandasでは、主にNumPyのnp.nanとして表現されます。
なぜ欠損値の処理がデータ分析に不可欠なのでしょうか?
-
分析の正確性: 欠損値が含まれたまま計算を行うと、合計値や平均値、標準偏差などが不正確になる可能性があります。
-
モデルの性能: 機械学習モデルは欠損値に対応できないことが多く、前処理として欠損値を適切に扱う必要があります。
-
データの整合性: 欠損値の存在は、データ収集プロセスにおける問題や、特定の条件下でのデータの不足を示唆することがあります。
-
可視化の課題: 欠損値を含むデータは、グラフ化する際に意図しない結果を生むことがあります。
1. 欠損値の確認
欠損値処理の第一歩は、データセット内にどれくらいの欠損値が存在するかを確認することです。
isnull() / isna() で欠損値を判定
isnull()(またはそのエイリアスisna())は、各要素がNaNであるかどうかの真偽値(True/False)を返します。
import pandas as pd
import numpy as np
# サンプルDataFrameの作成
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8],
'C': [9, 10, 11, np.nan]
})
print("元のDataFrame:\n", df)
# 欠損値の有無を真偽値で表示
print("\n欠損値の判定 (isnull()):\n", df.isnull())
sum() と組み合わせて欠損値の数をカウント
isnull()の結果とsum()を組み合わせることで、列ごとの欠損値の数を簡単に確認できます。
# 各列の欠損値の数をカウント
print("\n各列の欠損値数:\n", df.isnull().sum())
# DataFrame全体の欠損値の総数をカウント
print("\nDataFrame全体の欠損値総数:", df.isnull().sum().sum())
2. 欠損値の除外(削除): dropna()
欠損値を含む行や列をデータセットから削除したい場合にdropna()メソッドを使用します。
欠損値を含む行を削除する (axis=0 またはデフォルト)
デフォルトでは、dropna()は欠損値が一つでも含まれる行を削除します。
# 欠損値を含む行を削除
df_dropped_rows = df.dropna()
print("\n欠損値を含む行を削除後:\n", df_dropped_rows)
解説:
df.dropna(): dfの各行をチェックし、NaNが一つでもあればその行全体を削除します。元のDataFrameは変更されません(inplace=Falseがデフォルト)。
欠損値を含む列を削除する (axis=1)
axis=1を指定することで、欠損値が一つでも含まれる列を削除できます。
# 欠損値を含む列を削除
df_dropped_cols = df.dropna(axis=1)
print("\n欠損値を含む列を削除後:\n", df_dropped_cols)
欠損値が「全て」の行/列を削除する (how='all')
how='all'を指定すると、その行(または列)の全ての値がNaNの場合にのみ削除します。
df_all_nan = pd.DataFrame({
'X': [1, np.nan, 3],
'Y': [np.nan, np.nan, np.nan], # この列は全てNaN
'Z': [4, 5, np.nan]
})
print("\n元のDataFrame (全てNaNの列あり):\n", df_all_nan)
# 全ての要素がNaNの列を削除
df_dropped_all_nan_cols = df_all_nan.dropna(axis=1, how='all')
print("\n全ての要素がNaNの列を削除後:\n", df_dropped_all_nan_cols)
3. 欠損値の置換(穴埋め): fillna()
欠損値を削除するのではなく、特定の値で埋めたい場合にfillna()メソッドを使用します。
特定のスカラ値で穴埋めする
0や平均値など、単一の値で欠損値を置き換えます。
# 欠損値を0で埋める
df_filled_zero = df.fillna(0)
print("\n欠損値を0で埋めた後:\n", df_filled_zero)
# 各列の平均値で埋める
df_filled_mean = df.fillna(df.mean())
print("\n各列の平均値で埋めた後:\n", df_filled_mean)
解説:
-
df.fillna(0): DataFrame内の全てのNaNを0に置き換えます。 -
df.fillna(df.mean()):df.mean()は各列の平均値を計算したSeriesを返します。fillna()はこれを適用し、各列のNaNをそれぞれの列の平均値で埋めます。
前の値で穴埋めする (method='ffill' / pad)
欠損値をその直前の有効な値で埋める(forward fill)。時系列データでよく使われます。
# 前の値で欠損値を埋める (ffill)
df_filled_ffill = df.fillna(method='ffill')
print("\n前の値で埋めた後 (ffill):\n", df_filled_ffill)
後ろの値で穴埋めする (method='bfill' / backfill)
欠損値をその直後の有効な値で埋める(backward fill)。
# 後ろの値で欠損値を埋める (bfill)
df_filled_bfill = df.fillna(method='bfill')
print("\n後ろの値で埋めた後 (bfill):\n", df_filled_bfill)
解説:
ffillとbfillは、欠損値の位置から見て前(または後ろ)に有効な値がない場合、そのNaNは埋められないことがあります。
4. 欠損値の抽出
特定の分析のために、欠損値がある行や列を抽出したい場合があります。
欠損値のある行を抽出する
isnull()とブールインデックスを組み合わせることで、欠損値を含む行を抽出できます。
# 欠損値を含む行を抽出 (いずれかの列にNaNがある行)
df_rows_with_nan = df[df.isnull().any(axis=1)]
print("\n欠損値を含む行:\n", df_rows_with_nan)
# 特定の列('A')に欠損値がある行を抽出
df_rows_nan_in_A = df[df['A'].isnull()]
print("\n'A'列に欠損値がある行:\n", df_rows_nan_in_A)
解説:
-
df.isnull().any(axis=1): 各行にNaNが一つでも存在するかどうかを判定し、Series(True/False)を返します。 -
df[条件]:この真偽値のSeriesを使って、DataFrameから条件に合致する行を抽出します。
欠損値のない行を抽出する (notnull() / notna())
notnull()(またはnotna())は、NaNでない要素を判定します。
# 欠損値がない行を抽出
df_rows_no_nan = df[df.notnull().all(axis=1)]
print("\n欠損値がない行:\n", df_rows_no_nan)
解説:
df.notnull().all(axis=1): 各行の全ての要素がNaNでない場合にTrueとなるSeriesを返します。
まとめ
Pandasにおける欠損値処理は、データ分析の品質を担保するために不可欠なプロセスです。NaNを適切に扱うことで、より正確で信頼性の高い分析結果を得ることができます。
-
確認:
isnull()/isna()とsum()で欠損値の有無と数を把握。 -
除外(削除):
dropna()で欠損値を含む行や列を削除。 -
置換(穴埋め):
fillna()で欠損値を特定の値、前の値、後ろの値などで埋める。 -
抽出:
isnull()やnotnull()とブールインデックスを組み合わせて、欠損値のある/ない行を抽出。
これらのPandasの強力な機能とテクニックを使いこなすことで、欠損値に効率的に対処し、データ分析の質を格段に向上させることができるでしょう。ぜひ、あなたのデータクリーニングのワークフローにこれらのメソッドを取り入れてみてください。

