NumPy配列ndarrayの欠損値np.nanを含む行や列を削除
NumPy配列ndarrayの欠損値NaN(np.nan)を含む行・列を削除するには、np.isnan()で欠損値を判定し、any()やall()メソッドを使って欠損値が含まれていない行・列を抽出する。
PythonにおけるNaNの扱いについての基本は以下の記事を参照。
- 関連記事: Pythonにおけるnanの判定
欠損値を削除するのではなく他の値で置き換える場合は以下の記事を参照。
本記事のサンプルコードのNumPyのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。例として、データが欠落したCSVファイルをnp.genfromtxt()で読み込んで使う。欠落箇所が欠損値NaNとなる。
import numpy as np
print(np.__version__)
# 1.26.1
a = np.genfromtxt('data/src/sample_nan.csv', delimiter=',')
print(a)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. 33. 34.]]
ndarrayの欠損値NaNをすべて削除
要素が欠損値NaNか判定する関数np.isnan()を使って、欠損値の位置がTrueとなるndarrayを取得できる。
a = np.genfromtxt('data/src/sample_nan.csv', delimiter=',')
print(a)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. 33. 34.]]
print(np.isnan(a))
# [[False False True False]
# [False True True False]
# [False False False False]]
このndarrayに否定演算子~を使うと欠損値NaNの位置がFalseになり、これをマスクとして使うと欠損値を削除(欠損値ではない要素を抽出)できる。残る要素の個数がバラバラなので元の配列ndarrayの形状は維持されず、平坦化(一次元化)される。
print(~np.isnan(a))
# [[ True True False True]
# [ True False False True]
# [ True True True True]]
print(a[~np.isnan(a)])
# [11. 12. 14. 21. 24. 31. 32. 33. 34.]
ndarrayの欠損値NaNを含む行を削除
欠損値NaNを含む行を削除するには、ndarrayに一つでもTrueがあるとTrueを返すany()メソッドを使う。
引数axis=1とすると、各行に対して一つでもTrueがあるかどうかを判定する。
a = np.genfromtxt('data/src/sample_nan.csv', delimiter=',')
print(a)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. 33. 34.]]
print(np.isnan(a))
# [[False False True False]
# [False True True False]
# [False False False False]]
print(np.isnan(a).any(axis=1))
# [ True True False]
否定演算子~を使ってTrueとFalseを入れ替えると、欠損値が一つもない行がTrueとなる。
print(~np.isnan(a).any(axis=1))
# [False False True]
元のndarrayの行(一つ目の次元)に対してこのndarrayを適用することで、欠損値を含む行を削除(欠損値を含まない行を抽出)できる。
print(a[~np.isnan(a).any(axis=1), :])
# [[31. 32. 33. 34.]]
以下のように列の指定を省略してもよい。
print(a[~np.isnan(a).any(axis=1)])
# [[31. 32. 33. 34.]]
すべての要素が欠損値である行のみを削除するには、any()ではなくall()を使う。
引数axis=1とすると、各行に対してすべての要素がTrueかどうかを判定する。ここでは説明のために要素にnp.nanを代入している。
a[1, 0] = np.nan
a[1, 3] = np.nan
print(a)
# [[11. 12. nan 14.]
# [nan nan nan nan]
# [31. 32. 33. 34.]]
print(np.isnan(a).all(axis=1))
# [False True False]
print(~np.isnan(a).all(axis=1))
# [ True False True]
print(a[~np.isnan(a).all(axis=1)])
# [[11. 12. nan 14.]
# [31. 32. 33. 34.]]
ndarrayの欠損値NaNを含む列を削除
欠損値NaNを含む列を削除する場合も、行の場合と同様。
any()で引数axis=0とすると、各列に対して一つでもTrueがあるかどうかを判定する。否定演算子~を使って、一つも欠損値がない列をTrueとする。
a = np.genfromtxt('data/src/sample_nan.csv', delimiter=',')
print(a)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. 33. 34.]]
print(np.isnan(a))
# [[False False True False]
# [False True True False]
# [False False False False]]
print(np.isnan(a).any(axis=0))
# [False True True False]
print(~np.isnan(a).any(axis=0))
# [ True False False True]
元のndarrayの列(二つ目の次元)に対してこのndarrayを適用することで、欠損値を含む列を削除(欠損値を含まない列を抽出)できる。
print(a[:, ~np.isnan(a).any(axis=0)])
# [[11. 14.]
# [21. 24.]
# [31. 34.]]
すべての要素が欠損値である列のみを削除するには、any()ではなくall()を使う。ここでは説明のために要素にnp.nanを代入している。
a[2, 2] = np.nan
print(a)
# [[11. 12. nan 14.]
# [21. nan nan 24.]
# [31. 32. nan 34.]]
print(np.isnan(a).all(axis=0))
# [False False True False]
print(~np.isnan(a).all(axis=0))
# [ True True False True]
print(a[:, ~np.isnan(a).all(axis=0)])
# [[11. 12. 14.]
# [21. nan 24.]
# [31. 32. 34.]]