การจัดทำดัชนีแปลก ๆ โดยใช้จำนวนมาก


27

ฉันมีตัวแปร x นั่นคือรูปร่าง (2,2,50,100)

ฉันยังมีอาร์เรย์ y ที่เท่ากับ np.array ([0,10,20]) สิ่งประหลาดเกิดขึ้นเมื่อฉันทำดัชนี x [0,:,:,, y]

x = np.full((2,2,50,100),np.nan)
y = np.array([0,10,20])
print(x.shape)
(2,2,50,100)
print(x[:,:,:,y].shape)
(2,2,50,3)
print(x[0,:,:,:].shape)
(2,50,100)
print(x[0,:,:,y].shape)
(3,2,50)

ทำไมหนึ่งเอาต์พุตสุดท้าย (3,2,50) และไม่ใช่ (2,50,3)


ฉันเป็นคนใหม่ที่ไม่คุ้นเคยดังนั้นฉันไม่มีคำตอบสำหรับคำถามของคุณ ในการตรวจสอบนี้เพิ่มเติมฉันขอแนะนำให้หาตัวอย่างขนาดเล็กที่เป็นเพียง 2D หรือ 3D และเป็นเพียงองค์ประกอบมากที่สุด 10 ในแกนใด ๆ
รหัส - ผู้ฝึกงาน

คำตอบ:


21

นี่คือวิธีที่ numpy ใช้การจัดทำดัชนีขั้นสูงเพื่อกระจายรูปร่างของอาร์เรย์ เมื่อคุณผ่าน0สำหรับดัชนีแรกและyสำหรับดัชนีที่ผ่านมา numpy จะออกอากาศจะเป็นรูปร่างเช่นเดียวกับ0 yความเท่าเทียมกันดังต่อไปนี้ถือ: x[0,:,:,y] == x[(0, 0, 0),:,:,y]. นี่คือตัวอย่าง

import numpy as np

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

np.equal(x[0,:,:,y], x[(0, 0, 0),:,:,y]).all()
# returns:
True

ตอนนี้เนื่องจากคุณกำลังผ่านดัชนีสองชุดอย่างมีประสิทธิภาพคุณกำลังใช้ API การจัดทำดัชนีขั้นสูงเพื่อจัดทำดัชนี (ในกรณีนี้) คู่ของดัชนี

x[(0, 0, 0),:,:,y])

# equivalent to
[
  x[0,:,:,y[0]], 
  x[0,:,:,y[1]], 
  x[0,:,:,y[2]]
]

# equivalent to
rows = np.array([0, 0, 0])
cols = y
x[rows,:,:,cols]

# equivalent to
[
  x[r,:,:,c] for r, c in zip(rows, columns)
]

yซึ่งมีมิติที่แรกที่เดียวกับความยาวของ นี่คือสิ่งที่คุณเห็น

ตัวอย่างเช่นดูอาร์เรย์ที่มี 4 มิติซึ่งอธิบายไว้ในอันถัดไป:

x = np.arange(120).reshape(2,3,4,5)
y = np.array([0,2,4])

# x looks like:
array([[[[  0,   1,   2,   3,   4],    -+      =+
         [  5,   6,   7,   8,   9],     Sheet1  |
         [ 10,  11,  12,  13,  14],     |       |
         [ 15,  16,  17,  18,  19]],   -+       |
                                                Workbook1
        [[ 20,  21,  22,  23,  24],    -+       |
         [ 25,  26,  27,  28,  29],     Sheet2  |
         [ 30,  31,  32,  33,  34],     |       |
         [ 35,  36,  37,  38,  39]],   -+       |
                                                |
        [[ 40,  41,  42,  43,  44],    -+       |
         [ 45,  46,  47,  48,  49],     Sheet3  |
         [ 50,  51,  52,  53,  54],     |       |
         [ 55,  56,  57,  58,  59]]],  -+      =+


       [[[ 60,  61,  62,  63,  64],
         [ 65,  66,  67,  68,  69],
         [ 70,  71,  72,  73,  74],
         [ 75,  76,  77,  78,  79]],

        [[ 80,  81,  82,  83,  84],
         [ 85,  86,  87,  88,  89],
         [ 90,  91,  92,  93,  94],
         [ 95,  96,  97,  98,  99]],

        [[100, 101, 102, 103, 104],
         [105, 106, 107, 108, 109],
         [110, 111, 112, 113, 114],
         [115, 116, 117, 118, 119]]]])

x มีรูปแบบต่อเนื่องที่เข้าใจง่ายซึ่งตอนนี้เราสามารถใช้เพื่อแสดงสิ่งที่เกิดขึ้น ...

มิติแรกเหมือนกับสมุดงาน Excel 2 แผ่นส่วนข้อมูลที่สองเหมือนกับแผ่นงาน 3 แผ่นในสมุดงานแต่ละมิติส่วนที่สามนั้นมี 4 แถวต่อแผ่นและมิติสุดท้ายคือ 5 ค่าสำหรับแต่ละแถว (หรือคอลัมน์ต่อแผ่น)

เมื่อมองด้วยวิธีนี้การถามx[0,:,:,0]คือการพูดว่า: "ในเวิร์กบุ๊กแรกสำหรับแต่ละแผ่นสำหรับแต่ละแถวให้ค่า / คอลัมน์แรกให้ฉัน"

x[0,:,:,y[0]]
# returns:
array([[ 0,  5, 10, 15],
       [20, 25, 30, 35],
       [40, 45, 50, 55]])

# this is in the same as the first element in:
x[(0,0,0),:,:,y]

แต่ตอนนี้มีการจัดทำดัชนีขั้นสูงเราสามารถคิดว่าx[(0,0,0),:,:,y]"ในเวิร์กบุ๊กแรกสำหรับแต่ละแผ่นสำหรับแต่ละแถวให้ฉันyค่า th / คอลัมน์ฉันตกลงตอนนี้ทำมันสำหรับแต่ละค่าของy"

x[(0,0,0),:,:,y]
# returns:
array([[[ 0,  5, 10, 15],
        [20, 25, 30, 35],
        [40, 45, 50, 55]],

       [[ 2,  7, 12, 17],
        [22, 27, 32, 37],
        [42, 47, 52, 57]],

       [[ 4,  9, 14, 19],
        [24, 29, 34, 39],
        [44, 49, 54, 59]]])

ที่ใดที่มันคลั่งไคล้ก็คือคนอ้วนจะออกอากาศเพื่อจับคู่มิติด้านนอกของดัชนีอาเรย์ ดังนั้นหากคุณต้องการดำเนินการเช่นเดียวกับข้างต้น แต่สำหรับทั้ง "สมุดงาน Excel" คุณไม่จำเป็นต้องวนซ้ำและเรียงต่อกัน คุณสามารถส่งผ่านอาร์เรย์ไปยังมิติแรก แต่ต้องมีรูปร่างที่เข้ากันได้

y.shape == (3,)ผ่านจำนวนเต็มได้รับการถ่ายทอดไปยัง y.shapeหากคุณต้องการที่จะผ่านอาร์เรย์เป็นดัชนีแรกเพียงมิติสุดท้ายของอาร์เรย์จะต้องมีความเข้ากันได้กับ คือมิติสุดท้ายของดัชนีแรกจะต้องเป็น 3 หรือ 1

ix = np.array([[0], [1]])
x[ix,:,:,y].shape
# each row of ix is broadcast to length 3:
(2, 3, 3, 4)

ix = np.array([[0,0,0], [1,1,1]])
x[ix,:,:,y].shape
# this is identical to above:
(2, 3, 3, 4)

ix = np.array([[0], [1], [0], [1], [0]])
x[ix,:,:,y].shape
# ix is broadcast so each row of ix has 3 columns, the length of y
(5, 3, 3, 4)

พบคำอธิบายสั้น ๆ ในเอกสาร: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing


แก้ไข:

จากคำถามเดิมเพื่อรับซับไลน์หนึ่งรายการที่ต้องการคุณสามารถใช้x[0][:,:,y]:

x[0][:,:,y].shape
# returns
(2, 50, 3)

อย่างไรก็ตามหากคุณพยายามกำหนดให้กับส่วนย่อยเหล่านั้นคุณจะต้องระมัดระวังเป็นอย่างยิ่งว่าคุณกำลังดูมุมมองหน่วยความจำที่แชร์ของอาร์เรย์ดั้งเดิม มิฉะนั้นการมอบหมายจะไม่อยู่ในอาร์เรย์เดิม แต่เป็นสำเนา

หน่วยความจำที่ใช้ร่วมกันเกิดขึ้นเฉพาะเมื่อคุณกำลังใช้จำนวนเต็มหรือชิ้นไปยังระบบย่อยอาร์เรย์เช่นของคุณหรือ x[:,0:3,:,:]x[0,:,:,1:-1]

np.shares_memory(x, x[0])
# returns:
True

np.shares_memory(x, x[:,:,:,y])
# returns:
False

ทั้งคำถามดั้งเดิมของคุณและตัวอย่างของฉันyไม่ใช่ทั้ง int หรือ slice ดังนั้นจะสิ้นสุดการกำหนดให้กับสำเนาต้นฉบับเสมอ

แต่! เนื่องจากอาร์เรย์ของคุณyสามารถถูกแสดงเป็นส่วนย่อยคุณจึงสามารถรับมุมมองที่กำหนดได้ของอาร์เรย์ของคุณผ่าน:

x[0,:,:,0:21:10].shape
# returns:
(2, 50, 3)

np.shares_memory(x, x[0,:,:,0:21:10])
# returns:
True

# actually assigns to the original array
x[0,:,:,0:21:10] = 100

ที่นี่เราใช้ส่วนแบ่ง0:21:10เพื่อจับทุกดัชนีที่จะเข้าrange(0,21,10)มา เราต้องใช้21และไม่ใช่20เพราะจุดหยุดถูกแยกออกจากส่วนแบ่งเช่นเดียวกับในrangeฟังก์ชั่น

ดังนั้นโดยทั่วไปถ้าคุณสามารถสร้างชิ้นที่เหมาะกับเกณฑ์ย่อยของคุณคุณสามารถมอบหมาย


4

combining advanced and basic indexingมันถูกเรียกว่า ในการcombining advanced and basic indexingทำดัชนีจะต้องทำดัชนีในการจัดทำดัชนีขั้นสูงก่อนและ subspace / เชื่อมต่อผลลัพธ์กับมิติของการทำดัชนีพื้นฐาน

ตัวอย่างจากเอกสาร:

ให้ x.shape เท่ากับ(10,20,30,40,50)และสมมติว่า ind_1 และ ind_2 สามารถออกอากาศเป็นรูปร่าง (2,3,4) จากนั้น x [:, ind_1, ind_2] มีรูปร่าง (10,2,3,4,40,50) เนื่องจากสเปซย่อยรูปทรง (20,30) จาก X ถูกแทนที่ด้วยสเปซ (2,3,4) จาก ดัชนี อย่างไรก็ตามx [:, ind_1:, ind_2]มีรูปร่าง(2,3,4,10,30,50)เพราะไม่มีสถานที่ที่ชัดเจนที่จะลดลงในสเปซทำดัชนีดังนั้นจึงติดอยู่ในจุดเริ่มต้น เป็นไปได้เสมอที่จะใช้. tranpose () เพื่อย้ายพื้นที่ย่อยตามที่ต้องการ โปรดทราบว่าตัวอย่างนี้ไม่สามารถทำซ้ำได้โดยใช้การ

ดังนั้นในx[0,:,:,y], 0และyมีการจัดทำดัชนีล่วงหน้า (3,)พวกเขามีการออกอากาศร่วมกันเพื่อให้ผลผลิตมิติ

In [239]: np.broadcast(0,y).shape
Out[239]: (3,)

นี่(3,)จะเป็นการเริ่มต้นของมิติที่ 2 และ 3 ที่จะทำ(3, 2, 50)

หากต้องการดูว่าส่วนที่ 1 และส่วนสุดท้ายออกอากาศด้วยกันจริงๆคุณอาจลองเปลี่ยน0เป็น[0,1]เพื่อดูข้อผิดพลาดของการออกอากาศ

print(x[[0,1],:,:,y])

Output:
IndexError                                Traceback (most recent call last)
<ipython-input-232-5d10156346f5> in <module>
----> 1 x[[0,1],:,:,y]

IndexError: shape mismatch: indexing arrays could not be broadcast together with
 shapes (2,) (3,)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.