Memahami numpy.where

Oct 19 2020

Saya ingin mendapatkan indeks pertama dari elemen array numpy yang lebih besar dari beberapa elemen tertentu dari array yang sama. Saya mencoba mengikuti:

>>> 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

P1. Apakah cara di atas benar untuk mendapatkan indeks pertama suatu elemen di Q5[0]lebih besar dari Q5[0,0]?

Saya lebih peduli dengan np.where(Q5[0]>Q5[0,0])pengembalian tupel (array([1, 2], dtype=int32),)dan karenanya mengharuskan saya untuk menggandakan indeks [0][0]di akhir np.where(Q5[0]>Q5[0,0])[0][0].

P2. Mengapa ini mengembalikan tuple, tetapi di bawah ini mengembalikan array numpy yang tepat?

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

Sehingga saya bisa mengindeks langsung:

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

Jawaban

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.wherehanya dengan syaratnya sih np.nonzero.

Hasilkan array boolean:

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

Temukan di mana itu benar:

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

Hasilnya adalah tupel, satu elemen per dimensi kondisi. Setiap elemen adalah array pengindeksan, bersama-sama mereka menentukan lokasi True (s)

Tes lain dengan beberapa 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]))

Menggunakan tupel untuk mengindeks array asli:

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

Menggunakan argumen 3 whereuntuk membuat array baru dengan campuran nilai dari AdanA+10

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

Jika kondisi memiliki beberapa True, nonzerobukanlah alat uji untuk menemukan "pertama", karena ia harus menemukan semua.

Tupel bukan nol dapat diubah menjadi array 2d dengan a transpose. Sebenarnya mungkin lebih mudah untuk mendapatkan "pertama" dari larik ini:

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

Anda mencari dalam larik 1d, baris 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])

Jadi, apakah Anda mencari array 1d atau 2d (atau 3 atau 4), nonzeromengembalikan tupel dengan satu elemen array per dimensi. Dengan cara itu, ia selalu dapat digunakan untuk mengindeks larik berukuran serupa. Tupel 1d mungkin terlihat berlebihan, tetapi konsisten dengan hasil dimensi lainnya.

Saat mencoba memahami operasi seperti ini, baca dokumen dengan cermat, dan lihat langkah-langkah individu. Di sini saya melihat matriks bersyarat, nonzerohasilnya, dan berbagai kegunaannya.

AsafH Oct 19 2020 at 22:05

numpy.where () seperti loop for dengan if.

numpy.where(condition, values, new_value)

kondisi - seperti kondisi if.
nilai - Nilai yang akan diiterasi pada
nilai_baru - jika kondisinya benar untuk suatu nilai , ini akan berubah menjadi nilai_baru


Jika kita ingin menuliskannya untuk array 1 dimensi, tampilannya akan seperti ini:
[xv if c else yv 
for c, xv, yv in zip(condition, x, y)]

Contoh:

>>> 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])

Pertama kita membuat array dengan angka dari 0 sampai 9 (0, 1, 2 ... 7, 8, 9)
dan kemudian kita memeriksa semua nilai dalam array yang lebih besar dari 5 dan mengalikan nilainya dengan 10.
Jadi sekarang semua nilai dalam array yang kurang dari 5 tetap sama dan semua nilai yang lebih besar dikalikan dengan 10

wwii Oct 19 2020 at 21:41

Menggunakan argmaxdengan array boolean akan memberi Anda indeks True pertama.

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 dapat mengambil argumen sumbu / dimensi.

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

Yang mengatakan True yang pertama adalah indeks satu untuk kolom nol dan indeks nol untuk kolom satu dan dua.

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

Artinya True yang pertama adalah indeks satu untuk baris nol dan indeks nol untuk baris satu.


P1. Apakah cara di atas benar untuk mendapatkan indeks pertama suatu elemen di Q5 [0] lebih besar dari Q5 [0,0]?

Tidak, saya akan menggunakan argmaxwith 1untuk axisargumen lalu pilih item pertama dari hasil itu.

P2. Mengapa tuple kembali ini

Anda menyuruhnya mengembalikan -1nilai False dan mengembalikan Q5[0]item untuk nilai True.

Q2 ... tetapi di bawah ini mengembalikan array numpy yang tepat?

Anda beruntung dan memilih indeks yang benar.