1. ความหมายของรูปร่างใน NumPy
คุณเขียนว่า "ฉันรู้ว่ามันคือรายการของตัวเลขและรายการที่ทุกรายการมีเพียงตัวเลข" แต่นั่นเป็นวิธีที่ไม่มีประโยชน์ที่จะคิดเกี่ยวกับมัน
วิธีที่ดีที่สุดในการคิดเกี่ยวกับอาร์เรย์ NumPy คือประกอบด้วยสองส่วนบัฟเฟอร์ข้อมูลซึ่งเป็นเพียงบล็อกขององค์ประกอบดิบและมุมมองที่อธิบายวิธีตีความบัฟเฟอร์ข้อมูล
ตัวอย่างเช่นถ้าเราสร้างอาร์เรย์จำนวนเต็ม 12 จำนวน:
>>> a = numpy.arange(12)
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
จากนั้นa
ประกอบด้วยบัฟเฟอร์ข้อมูลจัดเรียงดังนี้:
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
และมุมมองที่อธิบายถึงวิธีการตีความข้อมูล:
>>> a.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : True
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)
ที่นี่รูปร่าง (12,)
หมายความว่าอาร์เรย์ถูกทำดัชนีโดยดัชนีเดี่ยวซึ่งเรียกใช้จาก 0 ถึง 11 ตามแนวคิดแล้วถ้าเราติดป้ายดัชนีเดี่ยวนี้i
อาร์เรย์a
จะมีลักษณะดังนี้:
i= 0 1 2 3 4 5 6 7 8 9 10 11
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
หากเราเปลี่ยนรูปร่างอาร์เรย์สิ่งนี้จะไม่เปลี่ยนบัฟเฟอร์ข้อมูล แต่จะสร้างมุมมองใหม่ที่อธิบายวิธีที่แตกต่างในการตีความข้อมูล ดังนั้นหลังจาก:
>>> b = a.reshape((3, 4))
อาร์เรย์b
มีบัฟเฟอร์ข้อมูลเหมือนกันa
แต่ตอนนี้มันถูกจัดทำดัชนีโดยดัชนีสองตัวที่รันจาก 0 ถึง 2 และ 0 ถึง 3 ตามลำดับ หากเราติดป้ายกำกับดัชนีทั้งสองi
และj
อาร์เรย์b
จะมีลักษณะดังนี้:
i= 0 0 0 0 1 1 1 1 2 2 2 2
j= 0 1 2 3 0 1 2 3 0 1 2 3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ซึ่งหมายความว่า:
>>> b[2,1]
9
คุณจะเห็นว่าดัชนีที่สองเปลี่ยนแปลงอย่างรวดเร็วและดัชนีแรกเปลี่ยนไปอย่างช้าๆ หากคุณต้องการให้สิ่งนี้เป็นรอบอื่น ๆ คุณสามารถระบุorder
พารามิเตอร์:
>>> c = a.reshape((3, 4), order='F')
ซึ่งผลลัพธ์ในอาร์เรย์ทำดัชนีดังนี้:
i= 0 1 2 0 1 2 0 1 2 0 1 2
j= 0 0 0 1 1 1 2 2 2 3 3 3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
ซึ่งหมายความว่า:
>>> c[2,1]
5
ตอนนี้มันควรจะชัดเจนว่ามันมีความหมายอย่างไรสำหรับอาเรย์ที่จะมีรูปร่างที่มีขนาดตั้งแต่หนึ่งขนาดขึ้นไปหลังจาก:
>>> d = a.reshape((12, 1))
อาเรย์d
ถูกทำดัชนีโดยดัชนีสองตัวอันแรกซึ่งรันจาก 0 ถึง 11 และดัชนีที่สองนั้นเป็น 0 เสมอ:
i= 0 1 2 3 4 5 6 7 8 9 10 11
j= 0 0 0 0 0 0 0 0 0 0 0 0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
และอื่น ๆ :
>>> d[10,0]
10
มิติของความยาว 1 คือ "ฟรี" (ในบางกรณี) ดังนั้นจึงไม่มีอะไรหยุดคุณจากการไปที่เมือง:
>>> e = a.reshape((1, 2, 1, 6, 1))
ให้อาร์เรย์จัดทำดัชนีเช่นนี้
i= 0 0 0 0 0 0 0 0 0 0 0 0
j= 0 0 0 0 0 0 1 1 1 1 1 1
k= 0 0 0 0 0 0 0 0 0 0 0 0
l= 0 1 2 3 4 5 0 1 2 3 4 5
m= 0 0 0 0 0 0 0 0 0 0 0 0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
และอื่น ๆ :
>>> e[0,1,0,0,0]
6
ดูเอกสารภายใน NumPyสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการใช้งานอาร์เรย์
2. จะทำอย่างไร?
ตั้งแต่ numpy.reshape
เพิ่งสร้างมุมมองใหม่คุณไม่ควรกลัวที่จะใช้มุมมองนี้เมื่อจำเป็น เป็นเครื่องมือที่เหมาะสมที่จะใช้เมื่อคุณต้องการจัดทำดัชนีอาร์เรย์ในวิธีอื่น
อย่างไรก็ตามในการคำนวณระยะยาวมักจะสามารถจัดเรียงเพื่อสร้างอาร์เรย์ที่มีรูปร่าง "ขวา" ในสถานที่แรกและเพื่อลดจำนวนของการปรับรูปร่างและ transposes แต่ถ้าไม่ได้เห็นบริบทจริงที่นำไปสู่ความต้องการการก่อร่างใหม่มันก็ยากที่จะพูดว่าควรจะเปลี่ยนแปลงอะไร
ตัวอย่างในคำถามของคุณคือ:
numpy.dot(M[:,0], numpy.ones((1, R)))
แต่นี่ไม่ใช่ความจริง ก่อนอื่นการแสดงออกนี้:
M[:,0].sum()
คำนวณผลลัพธ์ได้ง่ายขึ้น ประการที่สองมีอะไรพิเศษเกี่ยวกับคอลัมน์ 0 หรือไม่? บางทีสิ่งที่คุณต้องการคือ:
M.sum(axis=0)