ทำความเข้าใจกับ 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

คำถามที่ 1 วิธีที่ถูกต้องข้างต้นในการรับดัชนีแรกขององค์ประกอบQ5[0]มากกว่าQ5[0,0]หรือไม่?

ฉันกังวลมากขึ้นกับการnp.where(Q5[0]>Q5[0,0])ส่งคืนทูเปิล(array([1, 2], dtype=int32),)และด้วยเหตุนี้ฉันจึงต้องการดัชนีสองครั้ง[0][0]ในตอนท้ายของnp.where(Q5[0]>Q5[0,0])[0][0].

คำถามที่ 2 เหตุใดจึงส่งคืนทูเปิล แต่ด้านล่างส่งคืนอาร์เรย์จำนวนที่เหมาะสม

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

ผลลัพธ์คือทูเพิลหนึ่งองค์ประกอบต่อมิติของเงื่อนไข แต่ละองค์ประกอบเป็นอาร์เรย์การจัดทำดัชนีร่วมกันกำหนดตำแหน่งของ 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ไม่ใช่เครื่องมือทดสอบในการค้นหา "อันดับแรก" เนื่องจากจำเป็นต้องพบทั้งหมด

ทูเปิลที่ไม่ใช่ศูนย์สามารถเปลี่ยนเป็นอาร์เรย์ 2d ด้วย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) nonzeroจะส่งคืนทูเพิลที่มีองค์ประกอบอาร์เรย์หนึ่งรายการต่อมิติ ด้วยวิธีนี้จึงสามารถใช้ในการจัดทำดัชนีอาร์เรย์ที่มีขนาดเท่ากันได้เสมอ ทูเพิล 1d อาจดูซ้ำซ้อน แต่สอดคล้องกับผลลัพธ์มิติอื่น ๆ

เมื่อพยายามทำความเข้าใจการดำเนินการเช่นนี้โปรดอ่านเอกสารอย่างละเอียดและดูทีละขั้นตอน ที่นี่ฉันดูเมทริกซ์เงื่อนไขnonzeroผลลัพธ์และการใช้งานที่หลากหลาย

AsafH Oct 19 2020 at 22:05

numpy.where () เหมือนกับการวนซ้ำกับ if

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 ตัวแรกคือดัชนีหนึ่งสำหรับคอลัมน์ศูนย์และดัชนีศูนย์สำหรับคอลัมน์ที่หนึ่งและสอง

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

นั่นบอกว่า True แรกคือดัชนีหนึ่งสำหรับแถวศูนย์และดัชนีศูนย์สำหรับแถวที่หนึ่ง


คำถามที่ 1 วิธีที่ถูกต้องในการรับดัชนีแรกขององค์ประกอบใน Q5 [0] มากกว่า Q5 [0,0] หรือไม่

ไม่มีผมจะใช้argmaxกับ1สำหรับaxisอาร์กิวเมนต์แล้วเลือกรายการแรกจากผลการว่า

คำถามที่ 2 ทำไมต้องส่งคืนทูเพิล

คุณบอกให้ส่งคืน-1ค่า False และส่งคืนQ5[0]รายการสำหรับค่า True

Q2 ... แต่ด้านล่างส่งกลับอาร์เรย์จำนวนที่เหมาะสม?

คุณโชคดีและเลือกดัชนีที่ถูกต้อง