NumPy配列から欠損値np.nanを含む行・列をきれいに削除する方法
データ分析において、**欠損値(np.nan
)**の扱いは非常に重要です。特に、分析に不都合な欠損値を含む行や列をデータセットから取り除くことは、クリーンなデータで正確な結果を得るための一般的な前処理です。この記事では、NumPy配列(ndarray)に存在するnp.nan
を含む行や列を効率的に削除するためのテクニックを、具体的なサンプルコードを交えながら詳しく解説します。
欠損値を含む行・列を削除する目的
欠損値を含む行や列を削除する主な目的は以下の通りです。
分析の精度向上: 欠損値があると統計計算ができなかったり、結果に偏りが生じたりする可能性があります。
モデルの頑健性: 機械学習モデルの多くは欠損値に対応していないため、これらを削除することでモデルが適切に機能するようになります。
データの一貫性: 欠損値が散在しているとデータの一貫性が損なわれ、理解や可視化が難しくなります。
np.nan
を含む行を削除する方法
欠損値を含む行を削除するには、np.isnan()
とブールインデックス参照、またはnp.all()
やnp.any()
を組み合わせる方法が一般的です。
1. np.isnan()
とnp.any()
を組み合わせる
各行に一つでもnp.nan
が存在するかどうかをnp.any()
で判定し、その結果を使ってnp.nan
を含まない行のみを抽出します。これが最も推奨される方法です。
サンプルコード
import numpy as np
arr_2d = np.array([[1, 2, 3],
[4, np.nan, 6],
[7, 8, np.nan],
[10, 11, 12]])
print("元の配列:\n", arr_2d)
# 各行にNaNが存在するかどうかを判定 (TrueならNaNあり)
has_nan_row = np.isnan(arr_2d).any(axis=1)
print("\n各行にNaNがあるか:", has_nan_row)
# NaNを含まない行のみを抽出(つまりNaNを含む行を削除)
arr_cleaned_rows = arr_2d[~has_nan_row] # `~` でブール配列を反転
print("\nNaNを含む行を削除した配列:\n", arr_cleaned_rows)
出力例
元の配列:
[[ 1. 2. 3.]
[ 4. nan 6.]
[ 7. 8. nan]
[10. 11. 12.]]
各行にNaNがあるか: [False True True False]
NaNを含む行を削除した配列:
[[ 1. 2. 3.]
[10. 11. 12.]]
np.nan
を含む列を削除する方法
行の削除と同様に、np.isnan()
とnp.any()
を組み合わせて、列方向に適用することでnp.nan
を含む列を削除できます。
1. np.isnan()
とnp.any()
を組み合わせる
各列に一つでもnp.nan
が存在するかどうかをnp.any()
で判定し、その結果を使ってnp.nan
を含まない列のみを抽出します。
サンプルコード
import numpy as np
arr_2d = np.array([[1, np.nan, 3],
[4, 5, 6],
[7, np.nan, 9],
[10, 11, 12]])
print("元の配列:\n", arr_2d)
# 各列にNaNが存在するかどうかを判定 (TrueならNaNあり)
has_nan_col = np.isnan(arr_2d).any(axis=0)
print("\n各列にNaNがあるか:", has_nan_col)
# NaNを含まない列のみを抽出(つまりNaNを含む列を削除)
arr_cleaned_cols = arr_2d[:, ~has_nan_col] # `~` でブール配列を反転
print("\nNaNを含む列を削除した配列:\n", arr_cleaned_cols)
出力例
元の配列:
[[ 1. nan 3.]
[ 4. 5. 6.]
[ 7. nan 9.]
[10. 11. 12.]]
各列にNaNがあるか: [False True False]
NaNを含む列を削除した配列:
[[ 1. 3.]
[ 4. 6.]
[ 7. 9.]
[10. 12.]]
Pandasとの連携(より簡単な欠損値削除)
NumPy単独でも欠損値を含む行・列を削除できますが、データフレームとして欠損値を扱う場合は、Pandasライブラリのdropna()
メソッドが非常に便利です。NumPy配列を一時的にPandas DataFrameに変換してdropna()
を使用し、再度NumPy配列に戻すことも可能です。
サンプルコード
import numpy as np
import pandas as pd # Pandasライブラリのインポート
arr_2d = np.array([[1, np.nan, 3],
[4, 5, 6],
[7, np.nan, np.nan],
[10, 11, 12]])
print("元の配列:\n", arr_2d)
# NumPy配列をPandas DataFrameに変換
df = pd.DataFrame(arr_2d)
# NaNを含む行を削除
df_cleaned_rows = df.dropna(axis=0) # axis=0 で行を削除
print("\nPandasでNaNを含む行を削除したDataFrame:\n", df_cleaned_rows)
# NaNを含む列を削除
df_cleaned_cols = df.dropna(axis=1) # axis=1 で列を削除
print("\nPandasでNaNを含む列を削除したDataFrame:\n", df_cleaned_cols)
# 結果をNumPy配列に戻す場合
np_cleaned_rows = df_cleaned_rows.to_numpy()
print("\nPandasで処理後、NumPy配列に戻したもの:\n", np_cleaned_rows)
出力例
元の配列:
[[ 1. nan 3.]
[ 4. 5. 6.]
[ 7. nan nan]
[10. 11. 12.]]
PandasでNaNを含む行を削除したDataFrame:
0 1 2
1 4.0 5.0 6.0
3 10.0 11.0 12.0
PandasでNaNを含む列を削除したDataFrame:
0 2
0 1.0 3.0
1 4.0 6.0
2 7.0 NaN
3 10.0 12.0
Pandasで処理後、NumPy配列に戻したもの:
[[ 4. 5. 6.]
[10. 11. 12.]]
まとめ
NumPy配列からnp.nan
を含む行や列を削除することは、データ前処理の重要なステップです。
NumPyのブールインデックス参照:
np.isnan()
とnp.any()
(またはnp.all()
)を組み合わせることで、欠損値を含む行や列を効率的に特定し、削除(実質的には欠損値を含まない部分を抽出)できます。行を削除する場合:
arr[~np.isnan(arr).any(axis=1)]
列を削除する場合:
arr[:, ~np.isnan(arr).any(axis=0)]
Pandasの
dropna()
: より大規模なデータセットや、データフレーム形式で欠損値を扱う場合は、Pandasのdropna()
メソッドが非常に強力で、より直感的に操作できます。必要に応じてNumPy配列とPandas DataFrameを相互変換することで、両者の利点を活用できます。
これらのテクニックを習得することで、欠損値を含むデータセットを自信を持って扱い、クリーンで分析に適したNumPy配列を作成できるようになるでしょう。