【Pandasデータ前処理】欠損値NaNを含む行・列をきれいに削除!dropna徹底解説
データ分析の際、欠損値 (NaN) は避けて通れない問題です。特に、数値計算や統計処理を行う上で、NaNが含まれていると予期せぬエラーや誤った結果につながることがあります。Pandasのdropna
メソッドは、このような欠損値を効率的に削除(除外)するための非常に便利な機能です。この記事では、dropna
の基本的な使い方から、知っておくと役立つ応用例まで、短いサンプルコードと丁寧な解説でご紹介します。
dropna
メソッドとは?なぜ欠損値を削除するのか?
dropna
メソッドは、PandasのDataFrameやSeriesから欠損値(NaN、None、pd.NAなど)を含む行や列を削除するために使用されます。欠損値を削除する主な理由は以下の通りです。
分析の正確性向上: 欠損値があると、平均値や標準偏差などの統計計算が正しく行えない場合があります。
モデル学習の安定化: 機械学習モデルは欠損値に対応できないことが多く、エラーの原因となります。
データセットのクリーンアップ: 不要な欠損値を取り除くことで、データセット全体をきれいに保ち、理解しやすくします。
dropna
の基本的な使い方
まずは、dropna
メソッドの最も基本的な使い方を見ていきましょう。
欠損値を含む行を削除する
デフォルトでは、dropna
はNaNが1つでも含まれる行を削除します。
import pandas as pd
import numpy as np
# サンプルDataFrameの作成
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': ['apple', 'banana', 'orange', np.nan],
'C': [True, False, True, False]
})
print("オリジナルDataFrame:\n", df)
# 欠損値を含む行を削除
df_cleaned_rows = df.dropna()
print("\n欠損値を含む行を削除後:\n", df_cleaned_rows)
解説:
上記の例では、インデックス2(’A’列にnp.nan)とインデックス3(’B’列にnp.nan)の行が削除されました。
欠損値を含む列を削除する
axis=1
(またはaxis='columns'
)を指定すると、NaNが1つでも含まれる列を削除できます。
# 欠損値を含む列を削除
df_cleaned_cols = df.dropna(axis=1)
print("\n欠損値を含む列を削除後:\n", df_cleaned_cols)
解説:
‘A’列と’B’列にnp.nanが含まれているため、これらの列が削除され、’C’列だけが残ります。
dropna
の応用的な使い方
dropna
メソッドは、より柔軟な欠損値の削除を可能にするための引数も持っています。
特定の条件下で欠損値を削除する: how
引数
how
引数を使うと、行または列を削除する条件を指定できます。
how='all'
:すべてNaNの場合のみ削除
how='all'
を指定すると、すべての値がNaNである行または列のみを削除します。
df_all_nan = pd.DataFrame({
'X': [1, np.nan, np.nan],
'Y': [np.nan, np.nan, np.nan], # すべてNaNの列
'Z': [3, 4, np.nan]
})
print("\n'all'適用前DataFrame:\n", df_all_nan)
# すべてNaNの行を削除
df_cleaned_all_rows = df_all_nan.dropna(how='all')
print("\nすべての値がNaNの行を削除後:\n", df_cleaned_all_rows)
# すべてNaNの列を削除
df_cleaned_all_cols = df_all_nan.dropna(axis=1, how='all')
print("\nすべての値がNaNの列を削除後:\n", df_cleaned_all_cols)
解説:
行の場合、どの行もすべてNaNではないため、行は削除されません。
列の場合、
'Y'
列はすべてNaNなので削除されます。
how='any'
:一つでもNaNがあれば削除(デフォルト)
これはdropna()
のデフォルトの挙動と同じです。
# df_cleaned_rows = df.dropna(how='any') # 上記と同じ結果
閾値を設定して削除する: thresh
引数
thresh
引数を使うと、欠損値でない値が少なくともいくつ存在する場合に、その行(または列)を残すかを指定できます。
df_thresh = pd.DataFrame({
'P': [1, np.nan, 3, np.nan],
'Q': [5, 6, np.nan, np.nan],
'R': [7, 8, 9, 10]
})
print("\n'thresh'適用前DataFrame:\n", df_thresh)
# 欠損値でない値が2つ以上ある行のみ残す
df_cleaned_thresh = df_thresh.dropna(thresh=2)
print("\n欠損値でない値が2つ以上ある行を保持後:\n", df_cleaned_thresh)
解説:
インデックス
0
([1, 5, 7]
):NaNではない値が3つなので残ります。インデックス
1
([nan, 6, 8]
):NaNではない値が2つなので残ります。インデックス
2
([3, nan, 9]
):NaNではない値が2つなので残ります。インデックス
3
([nan, nan, 10]
):NaNではない値が1つ(10
のみ)なので削除されます。
特定の列に基づいて欠損値を削除する: subset
引数
subset
引数に列名のリストを指定すると、指定した列に欠損値がある行のみを削除します。他の列にNaNがあっても、指定した列になければその行は削除されません。
df_subset = pd.DataFrame({
'X': [1, 2, np.nan, 4],
'Y': [5, np.nan, 7, 8],
'Z': [9, 10, 11, np.nan]
})
print("\n'subset'適用前DataFrame:\n", df_subset)
# 'X'列に欠損値がある行のみを削除
df_cleaned_subset = df_subset.dropna(subset=['X'])
print("\n'X'列に欠損値がある行を削除後:\n", df_cleaned_subset)
解説:
‘X’列にnp.nanがあるインデックス2の行のみが削除されています。’Y’列や’Z’列にNaNがあっても、’X’列にNaNがなければその行は残ります。
注意点: inplace
引数
dropna
メソッドはデフォルトで、新しいDataFrameまたはSeriesを返します。元のオブジェクトを直接変更したい場合は、inplace=True
を設定します。
# 例: inplace=Trueの使用(非推奨とされることが多い)
df_inplace = pd.DataFrame({'A': [1, np.nan], 'B': [3, 4]})
print("inplace適用前DataFrame:\n", df_inplace)
df_inplace.dropna(inplace=True)
print("\ninplace適用後DataFrame:\n", df_inplace)
解説:
inplace=Trueはメモリ効率が良いとされますが、元のデータを上書きしてしまうため、予期せぬ挙動につながる可能性があります。通常は、df_cleaned = df.dropna()のように、新しい変数に代入する方が安全で推奨される方法です。
まとめ
Pandasのdropna
メソッドは、DataFrameやSeriesから欠損値を含む行や列を柔軟に削除するための強力なツールです。基本的な使い方から、how
、thresh
、subset
といった引数を組み合わせることで、データの特性に応じたきめ細やかな前処理が可能になります。データ分析の品質を高めるために、これらの機能をぜひ活用してみてください。