Pythonのnumpy.where()メソッドの使用方法

Pythonでは、numpy.where()関数を使用して、条件に基づいてNumPy配列から要素を選択できます。

それだけでなく、条件が満たされている場合には、それらの要素にいくつかの操作を行うこともできます。

この関数をどのように使用するか、いくつかの具体的な例を用いて見てみましょう!


Python numpy.where()の構文

この関数は、NumPyのような配列(例:整数/ブール値のNumPy配列)を受け取ります。NumPy配列を受け取り、それを

条件に基づいてフィルタリングした新しいNumPy配列を返します。条件は、ブール値のNumPy配列です。

例えば、conditionarray([[True, True, True]])という値を取り、これはNumPyのブール配列です。(デフォルトでは、NumPyは数値値のみをサポートしていますが、これらをboolにキャストすることもできます)

例えば、conditionarray([[True, True, False]])であり、配列がa = ndarray([[1, 2, 3]])である場合、配列に条件を適用すると(a[:, condition])、配列ndarray([[1 2]])が得られます。

import numpy as np

a = np.arange(10)
print(a[a <= 2]) # 2以下の要素のみをキャプチャし、他の要素は無視します

出力

array([0 1 2])

注意: 同じ条件は a <= 2 としても表現できます。これは条件配列の推奨される形式であり、ブール配列として書くのは非常に面倒です。

しかし、結果の次元を保持し、元の配列から要素を失わないようにしたい場合はどうでしょうか?そのためには numpy.where() を使用できます。

numpy.where(condition [, x, y])

さらに、xy という2つの追加パラメータがあります。それらは何ですか?

基本的に、これは私たちの配列の要素のうち、condition が真である場合、新しい配列は x から要素を選択するということです。

それ以外の場合、偽であれば y から要素が取得されます。

これにより、最終的な出力配列は、condition = True の場合には x から要素を持ち、condition = False の場合には y から要素を持つ配列になります。

xy がオプションであることに注意してくださいが、x を指定した場合は 必ず y も指定する必要があります。これは、この場合において、出力配列の形状が入力配列と同じでなければならないためです。

注意: 同じ論理が単一次元配列と多次元配列の両方に適用されます。両方の場合、条件に基づいてフィルタリングされます。また、xycondition の形状が一緒にブロードキャストされることを覚えておいてください。

さて、この関数を正しく理解するために、いくつかの例を見てみましょう。


Pythonのnumpy.where()の使用

numpy.where()を使用して、numpy配列から正の要素のみを取り出し、すべての負の要素を0に設定したいとします。そのために、numpy.where()を使用したコードを書いてみましょう。

1. numpy.where()を使った要素の置換

ここでは、2次元のランダム配列を使用し、正の要素のみを出力します。

import numpy as np

# aのランダムな初期化(2次元配列)
a = np.random.randn(2, 3)
print(a)

# 条件が真の場合に、bはaのすべての要素となります(つまり、正の要素のみ)
# それ以外の場合は、0に設定します
b = np.where(a > 0, a, 0)

print(b)

可能な出力

[[-1.06455975  0.94589166 -1.94987123]
 [-1.72083344 -0.69813711  1.05448464]]
[[0.         0.94589166 0.        ]
 [0.         0.         1.05448464]]

ご覧のように、正の要素のみが残っています!

2. 条件のみを使用したnumpy.where()の使用

上記のコードに関しては、混乱があるかもしれません。いくつかの方は、より直感的な方法は、単に次のように条件を書くことだろうと考えるかもしれません:

import random
import numpy as np

a = np.random.randn(2, 3)
b = np.where(a > 0)
print(b)

上記のコードをこの変更で実行してみると、次のような出力が得られます:

(array([0, 1]), array([2, 1]))

注意してみると、bは今、NumPy配列のタプルです。そして、それぞれの配列は正の要素の位置です。これは何を意味するのでしょうか?

条件だけを提供すると、この関数は実際にはnp.asarray.nonzero()と等価です。

例えば、np.asarray(a > 0)は条件を適用した後にブール型の配列を返し、np.nonzero(arr_like)arr_likeの非ゼロ要素のインデックスを返します。(こちらを参照)

したがって、numpyではどれだけ柔軟であるかを示す、よりシンプルな例を見てみましょう!

import numpy as np

a = np.arange(10)

b = np.where(a < 5, a, a * 10)

print(a)
print(b)

出力

[0 1 2 3 4 5 6 7 8 9]
[ 0  1  2  3  4 50 60 70 80 90]

ここで、条件はa < 5であり、それはNumPy風の配列[True True True True True False False False False False]になります。xは配列aであり、yは配列a * 10です。したがって、a < 5の場合はaから選択し、a * 10の場合はa > 5から選択します。

したがって、これはすべての要素を10倍に変換します。これが実際に得られるものです!


numpy.where() を使ったブロードキャスト

もし、すべての条件、x、およびyの配列を提供した場合、numpyはそれらを一緒にブロードキャストします。

import numpy as np

a = np.arange(12).reshape(3, 4)

b = np.arange(4).reshape(1, 4)

print(a)
print(b)

# ブロードキャスト (a < 5, a、および b * 10)
# 形状は (3, 4)、(3, 4)、および (1, 4)
c = np.where(a < 5, a, b * 10)

print(c)

出力

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
[[0 1 2 3]]
[[ 0  1  2  3]
 [ 4 10 20 30]
 [ 0 10 20 30]]

ここでも、出力は条件に基づいて選択されるため、すべての要素が対象ですが、ここではbaの形状にブロードキャストされます(その次元の1つには要素が1つしかないため、ブロードキャスト中にエラーは発生しません)。

したがって、b[[0 1 2 3] [0 1 2 3] [0 1 2 3]]となり、今度はこのブロードキャストされた配列から要素を選択できます。

したがって、出力の形状はaの形状と同じです。


結論

この記事では、Pythonのnumpy.where()関数を使用して他の条件配列に基づいて配列を選択する方法について学びました。


参考文献


Source:
https://www.digitalocean.com/community/tutorials/python-numpy-where