note.nkmk.me

NumPy配列ndarrayから条件を満たす要素・行・列を抽出、削除

Date: 2018-03-08 / tags: Python, NumPy

NumPy配列ndarrayから条件を満たす要素・行・列を抽出(取得)または削除する方法をサンプルコードとともに説明する。

ここでは、

  • 条件を満たす要素を抽出
  • 条件を満たす行・列を抽出
    • numpy.all()ですべての要素が条件を満たす行・列を抽出
    • numpy.any()で条件を満たす要素が一つでもある行・列を抽出
  • 条件を満たす要素・行・列を削除
    • 否定演算子~を利用
    • numpy.delete()numpy.where()を利用
  • 複数条件の場合

について説明する。

データが欠落しているcsvファイルを読み込んだ場合など、ndarraynanが含まれている場合は以下の記事を参照。

条件を満たす要素を置換したい場合は以下の記事を参照。

また、条件ではなくスライスやリストで行・列を抽出したい場合は以下の記事を参照。

スポンサーリンク

条件を満たす要素を抽出

条件を満たす要素を抽出したい場合は、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を返し、そうでないときはFlaseを返す関数。

引数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()は第一引数に渡したndarrayTrueの要素が一つでもあるときにTrueを返し、そうでないときはFlaseを返す関数。

引数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]]
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事