NumPy配列ndarrayから条件を満たす要素・行・列を抽出、削除 | note.nkmk.me (original) (raw)
NumPy配列ndarray
から条件を満たす要素・行・列を抽出(取得)または削除する方法をサンプルコードとともに説明する。
ここでは、
- 条件を満たす要素を抽出
- 条件を満たす行・列を抽出
numpy.all()
ですべての要素が条件を満たす行・列を抽出numpy.any()
で条件を満たす要素が一つでもある行・列を抽出
- 条件を満たす要素・行・列を削除
- 否定演算子
~
を利用 numpy.delete()
とnumpy.where()
を利用
- 否定演算子
- 複数条件の場合
について説明する。
データが欠落しているcsvファイルを読み込んだ場合など、ndarray
にnan
が含まれている場合は以下の記事を参照。
条件を満たす要素を置換したりカウントしたりしたい場合は以下の記事を参照。
また、条件ではなくスライスやリストで行・列を抽出したい場合は以下の記事を参照。
条件を満たす要素を抽出
条件を満たす要素を抽出したい場合は、ndarray[条件式]
とすればよい。
元のndarray
が多次元配列の場合でも、返されるのは平坦化された一次元配列。
`import numpy as np
a = np.arange(12).reshape((3, 4)) print(a)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
print(a < 5)
[[ True True True True]
[ True False False False]
[False False False False]]
print(a[a < 5])
[0 1 2 3 4]
print(a < 10)
[[ True True True True]
[ True True True True]
[ True True False False]]
print(a[a < 10])
[0 1 2 3 4 5 6 7 8 9]
`
新たな配列ndarray
を返し、元のndarray
は変更されない。以降の例も同じ。
`b = a[a < 10] print(b)
[0 1 2 3 4 5 6 7 8 9]
print(a)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
`
条件を満たす要素の合計sum()
や平均mean()
、最大値max()
、最小値min()
、標準偏差std()
なども算出できる。
`print(a[a < 5].sum())
10
print(a[a < 5].mean())
2.0
print(a[a < 5].max())
4
print(a[a < 10].min())
0
print(a[a < 10].std())
2.8722813232690143
`
条件を満たす行・列を抽出
要素を抽出する例では一次元配列が返されたが、np.all()
, np.any()
を使うと元のndarray
の次元を保ったまま行・列を抽出できる。
以下の二通りについて説明する。
numpy.all()
: すべての要素が条件を満たす行・列を抽出numpy.any()
: 条件を満たす要素が一つでもある行・列を抽出
numpy.all()ですべての要素が条件を満たす行・列を抽出
np.all()
は第一引数に渡したndarray
の要素がすべてTrue
のときにTrue
を返し、そうでないときはFalse
を返す関数。
引数axis
を渡すと、各軸(各次元)それぞれに対してすべての要素がTrue
のときにTrue
を返す。二次元配列の場合はaxis=0
が列に対して、axis=1
が行に対しての結果となる。
`print(a < 5)
[[ True True True True]
[ True False False False]
[False False False False]]
print(np.all(a < 5))
False
print(np.all(a < 5, axis=0))
[False False False False]
print(np.all(a < 5, axis=1))
[ True False False]
print(a < 10)
[[ True True True True]
[ True True True True]
[ True True False False]]
print(np.all(a < 10, axis=0))
[ True True False False]
print(np.all(a < 10, axis=1))
[ True True False]
`
それぞれの結果を行または列のインデックス参照[行, 列]
に与えると所望の行・列が抽出される。[行, :]
の場合、末尾の, :
は省略できる。
`print(a[:, np.all(a < 10, axis=0)])
[[0 1]
[4 5]
[8 9]]
print(a[np.all(a < 10, axis=1), :])
[[0 1 2 3]
[4 5 6 7]]
print(a[np.all(a < 10, axis=1)])
[[0 1 2 3]
[4 5 6 7]]
`
条件を満たさない場合は空のndarray
が返る。
`print(a[:, np.all(a < 5, axis=0)])
[]
`
一行だけあるいは一列だけの場合も次元数は変わらない。
`print(a[np.all(a < 5, axis=1)])
[[0 1 2 3]]
print(a[np.all(a < 5, axis=1)].ndim)
2
print(a[np.all(a < 5, axis=1)].shape)
(1, 4)
`
numpy.any()で条件を満たす要素が一つでもある行・列を抽出
np.any()
は第一引数に渡したndarray
にTrue
の要素が一つでもあるときにTrue
を返し、そうでないときはFalse
を返す関数。
引数axis
を渡すと、各軸(各次元)それぞれに対してTrue
の要素が一つでもあるときにTrue
を返す。二次元配列の場合はaxis=0
が列に対して、axis=1
が行に対しての結果となる。
`print(a < 5)
[[ True True True True]
[ True False False False]
[False False False False]]
print(np.any(a < 5))
True
print(np.any(a < 5, axis=0))
[ True True True True]
print(np.any(a < 5, axis=1))
[ True True False]
`
np.all()
と同じ要領で条件に合致した行・列を抽出できる。
`print(a[:, np.any(a < 5, axis=0)])
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
print(a[np.any(a < 5, axis=1)])
[[0 1 2 3]
[4 5 6 7]]
`
条件を満たす要素・行・列を削除
条件に応じて要素・行・列を抽出(取得)するのではなく削除したい場合は、以下の二通りの方法がある。
- 否定演算子
~
を利用 numpy.delete()
とnumpy.where()
を利用
否定演算子を利用
条件に否定演算子~
をつけると条件を満たさない要素・行・列が抽出される。これは条件を満たす要素・行・列を削除するのと等価。
`print(a[~(a < 5)])
[ 5 6 7 8 9 10 11]
print(a[:, np.all(a < 10, axis=0)])
[[0 1]
[4 5]
[8 9]]
print(a[:, ~np.all(a < 10, axis=0)])
[[ 2 3]
[ 6 7]
[10 11]]
print(a[np.any(a < 5, axis=1)])
[[0 1 2 3]
[4 5 6 7]]
print(a[~np.any(a < 5, axis=1)])
[[ 8 9 10 11]]
`
numpy.delete()とnumpy.where()を利用
行・列はnp.delete()
とnp.where()
を利用して削除することもできる。
np.delete()
は、対象となるndarray
と削除するインデックス(行番号、列番号など)、対象となる軸(次元)axis
を引数で設定する。
二次元配列の場合はaxis=0
が行の削除、axis=1
が列の削除で、上述のnp.all()
, np.any()
と違うので注意。
`print(a)
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
print(np.delete(a, [0, 2], axis=0))
[[4 5 6 7]]
print(np.delete(a, [0, 2], axis=1))
[[ 1 3]
[ 5 7]
[ 9 11]]
`
np.delete()
については以下の記事も参照。
np.where()
は条件を満たす要素のインデックスを返す。
多次元配列の場合は、各次元(行、列)に対して条件を満たすインデックス(行番号、列番号)のリストのタプルとなる。
`print(a < 2)
[[ True True False False]
[False False False False]
[False False False False]]
print(np.where(a < 2))
(array([0, 0]), array([0, 1]))
print(np.where(a < 2)[0])
[0 0]
print(np.where(a < 2)[1])
[0 1]
`
np.where()
については以下の記事も参照。
この二つの関数を組み合わせると、条件を満たす行・列を削除できる。
`print(np.delete(a, np.where(a < 2)[0], axis=0))
[[ 4 5 6 7]
[ 8 9 10 11]]
print(np.delete(a, np.where(a < 2)[1], axis=1))
[[ 2 3]
[ 6 7]
[10 11]]
print(a == 6)
[[False False False False]
[False False True False]
[False False False False]]
print(np.where(a == 6))
(array([1]), array([2]))
print(np.delete(a, np.where(a == 6)))
[ 0 3 4 5 6 7 8 9 10 11]
print(np.delete(a, np.where(a == 6)[0], axis=0))
[[ 0 1 2 3]
[ 8 9 10 11]]
print(np.delete(a, np.where(a == 6)[1], axis=1))
[[ 0 1 3]
[ 4 5 7]
[ 8 9 11]]
`
上の例の通り、条件を満たす要素が一つでもある行・列の削除(np.any()
を使った場合と同じ)となる。
np.where()
で取得したインデックスの個数をカウントするなどの処理を行えばすべての要素が条件を満たす行・列の削除(np.all()
を使った場合と同じ)も可能だが、np.all()
を使ったほうが簡単。
複数条件の場合
複数の条件を組み合わせたい場合は、それぞれの条件式を()
で囲み&
や|
でつなげればOK。
`print(a[(a < 10) & (a % 2 == 1)])
[1 3 5 7 9]
print(a[np.any((a == 2) | (a == 10), axis=1)])
[[ 0 1 2 3]
[ 8 9 10 11]]
print(a[:, ~np.any((a == 2) | (a == 10), axis=0)])
[[ 0 1 3]
[ 4 5 7]
[ 8 9 11]]
`