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を含まない行のみを抽出します。これが最も推奨される方法です。

 

サンプルコード

 

Python
 
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を含まない列のみを抽出します。

 

サンプルコード

 

Python
 
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配列に戻すことも可能です。

 

サンプルコード

 

Python
 
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配列を作成できるようになるでしょう。