numpy.whereを理解する

Oct 19 2020

同じ配列の特定の要素よりも大きいnumpy配列要素の最初のインデックスを取得したいと思います。私は以下を試しました:

>>> Q5=[[1,2,3],[4,5,6]]
>>> Q5 = np.array(Q5)
>>> Q5[0][Q5>Q5[0,0]]
array([2, 3])
>>> np.where(Q5[0]>Q5[0,0])
(array([1, 2], dtype=int32),)
>>> np.where(Q5[0]>Q5[0,0])[0][0]
1

Q1。Q5[0]より大きい要素の最初のインデックスを取得する正しい方法を上回っていQ5[0,0]ますか?

np.where(Q5[0]>Q5[0,0])タプルを返すことに関心がある(array([1, 2], dtype=int32),)ため[0][0]、の最後にインデックスを2つ追加する必要がありnp.where(Q5[0]>Q5[0,0])[0][0]ます。

Q2。なぜこれはタプルを返しますが、以下は適切なnumpy配列を返しますか?

>>> np.where(Q5[0]>Q5[0,0],Q5[0],-1)
array([-1,  2,  3])

直接インデックスを作成できるように:

>>> np.where(Q5[0]>Q5[0,0],Q5[0],-1)[1]
2

回答

hpaulj Oct 19 2020 at 21:42
In [58]: A = np.arange(1,10).reshape(3,3)
In [59]: A.shape
Out[59]: (3, 3)
In [60]: A
Out[60]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

np.where条件だけで本当にnp.nonzeroです。

ブール配列を生成します。

In [63]: A==6
Out[63]: 
array([[False, False, False],
       [False, False,  True],
       [False, False, False]])

それが真実である場所を見つけてください:

In [64]: np.nonzero(A==6)
Out[64]: (array([1]), array([2]))

結果はタプルであり、条件の次元ごとに1つの要素です。各要素はインデックス配列であり、一緒になってTrueの場所を定義します。

いくつかのTrueを使用した別のテスト

In [65]: (A%3)==1
Out[65]: 
array([[ True, False, False],
       [ True, False, False],
       [ True, False, False]])
In [66]: np.nonzero((A%3)==1)
Out[66]: (array([0, 1, 2]), array([0, 0, 0]))

タプルを使用して元の配列にインデックスを付ける:

In [67]: A[np.nonzero((A%3)==1)]
Out[67]: array([1, 4, 7])

3引数whereを使用して、Aとからの値を組み合わせた新しい配列を作成しますA+10

In [68]: np.where((A%3)==1,A+10, A)
Out[68]: 
array([[11,  2,  3],
       [14,  5,  6],
       [17,  8,  9]])

条件に複数のTrueがある場合、nonzeroそれは必然的にすべてを見つけるので、「最初の」を見つけるためのテストツールではありません。

ゼロ以外のタプルは、を使用して2次元配列に変換できますtranspose。実際には、この配列から「最初の」配列を取得する方が簡単な場合があります。

In [73]: np.argwhere((A%3)==1)
Out[73]: 
array([[0, 0],
       [1, 0],
       [2, 0]])

あなたは1d配列、Aの行を探しています:

In [77]: A[0]>A[0,0]
Out[77]: array([False,  True,  True])
In [78]: np.nonzero(A[0]>A[0,0])
Out[78]: (array([1, 2]),)            # 1 element tuple
In [79]: np.argwhere(A[0]>A[0,0])
Out[79]: 
array([[1],
       [2]])
In [81]: np.where(A[0]>A[0,0], 100, 0)     # 3 argument where
Out[81]: array([  0, 100, 100])

したがって、1d配列または2d(または3または4)のどちらを検索する場合でも、次元ごとに1つの配列要素を持つタプルをnonzero返します。そうすれば、同じサイズの配列にインデックスを付けるためにいつでも使用できます。1dタプルは冗長に見えるかもしれませんが、他の次元の結果と一致しています。

このような操作を理解しようとするときは、ドキュメントを注意深く読み、個々のステップを確認してください。ここでは、条件付き行列、nonzero結果、およびそのさまざまな使用法について説明します。

AsafH Oct 19 2020 at 22:05

numpy.where()は、ifを使用したforループのようなものです。

numpy.where(condition, values, new_value)

条件-条件の場合と同じように。
値-値を反復処理する上
NEW_VALUEは-あれば条件がために真である値、そのはに変更するつもりNEW_VALUE


1次元配列用に記述したい場合は、次のようになります。
[xv if c else yv 
for c, xv, yv in zip(condition, x, y)]

例:

>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> np.where(a < 5, a, 10*a)
array([ 0,  1,  2,  3,  4, 50, 60, 70, 80, 90])

最初に、0から9(0、1、2 ... 7、8、9)の数値で配列を作成し、
次に5より大きい配列内のすべての値をチェックし、それらの値に10を掛けます。
したがって、5未満の配列内のすべての値は同じままであり、それより大きいすべての値に10を掛けます。

wwii Oct 19 2020 at 21:41

argmaxブール配列とともに使用すると、最初のTrueのインデックスが得られます。

In [54]: q
Out[54]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [55]: q > q[0,0]
Out[55]: 
array([[False,  True,  True],
       [ True,  True,  True]], dtype=bool)

argmax 軸/寸法の引数を取ることができます。

In [56]: np.argmax(q > q[0,0], 0)
Out[56]: array([1, 0, 0], dtype=int64)

つまり、最初のTrueは、列0のインデックス1であり、列1と2のインデックス0です。

In [57]: np.argmax(q > q[0,0], 1)
Out[57]: array([1, 0], dtype=int64)

つまり、最初のTrueは、行0のインデックス1と行1のインデックス0です。


Q1。Q5 [0]の要素の最初のインデックスを取得する上記の正しい方法はQ5 [0,0]より大きいですか?

いいえ、引数にargmaxwith1を使用して、axisその結果から最初の項目を選択します。

Q2。なぜこれがタプルを返すのか

-1False値の場合は戻りQ5[0]、True値の場合はアイテムを返すように指示しました。

Q2 ...しかし、以下は適切なnumpy配列を返しますか?

あなたは幸運に恵まれ、正しいインデックスを選択しました。