NumPy配列ndarrayの欠損値np.nanを含む行や列を削除

Modified: | Tags: Python, NumPy

NumPy配列ndarrayの欠損値NaNnp.nan)を含む行・列を削除するには、np.isnan()で欠損値を判定し、any()all()メソッドを使って欠損値が含まれていない行・列を抽出する。

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]

否定演算子~を使ってTrueFalseを入れ替えると、欠損値が一つもない行が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.]]

関連カテゴリー

関連記事