ชิ้นดัชนีที่เป็นตัวเลขโดยไม่สูญเสียข้อมูลมิติ


100

ฉันใช้ numpy และต้องการจัดทำดัชนีแถวโดยไม่สูญเสียข้อมูลมิติข้อมูล

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10,:]
xslice.shape   # >> (10,)  

ในตัวอย่างนี้ xslice ตอนนี้เป็น 1 มิติ แต่ฉันต้องการให้เป็น (1,10) ใน R ฉันจะใช้ X [10,:, drop = F] มีบางอย่างที่คล้ายกันใน numpy ฉันไม่พบในเอกสารและไม่เห็นคำถามที่คล้ายกันนี้ถาม

ขอบคุณ!

คำตอบ:


59

มันอาจจะง่ายที่สุดในการทำx[None, 10, :]หรือเท่ากัน ( x[np.newaxis, 10, :]แต่อ่านได้มากขึ้น)

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

นอกจากนี้ numpy ยังจัดการอาร์เรย์กระจายเสียงได้เป็นอย่างดีดังนั้นจึงมีเหตุผลเพียงเล็กน้อยที่จะรักษาขนาดของอาร์เรย์ที่สไลซ์มา หากคุณทำสิ่งต่างๆเช่น:

a = np.zeros((100,100,10))
b = np.zeros(100,10)
a[0,:,:] = b

อาจไม่ได้ผลหรือจะยากกว่ามากในการนำไปใช้

(หรืออย่างน้อยนั่นก็คือการคาดเดาของฉันที่เหตุผลของนักพัฒนาที่เป็นตัวเลขที่อยู่เบื้องหลังการทิ้งข้อมูลมิติเมื่อหั่นบาง ๆ )


6
@ ลิซ่า: x[None, 10]จะทำในสิ่งที่คุณต้องการ
naught101

ได้. วางของคุณNoneถัดจากหรี่ที่คุณกำลังสับ
Mad Physicist

1
ตัวอย่างที่จะหายไปวงเล็บพิเศษสำหรับ tuple ในงานที่มอบหมายไปb; b = np.zeros((100,10))มันควรจะเป็น
Jerzy

เหตุผลในการใช้ดัชนีทั้งหมด 3 ตัวแทนที่จะเป็นเพียงสองดัชนี ฉันหมายถึงX[10,None](ใช้รหัสของคุณเป็นตัวอย่าง)
greenoldman

9
" มักจะมีเหตุผลเพียงเล็กน้อยที่จะรักษามิติของอาร์เรย์ไว้ " ... แน่นอนว่ามันจะทำให้การคูณเมทริกซ์ ( np.matmul()หรือ@ ) เสียหายอย่างสมบูรณ์ เพิ่งโดนเผานี่
Jean-François Corbett

93

อีกวิธีหนึ่งคือการทำ

X[[10],:]

หรือ

I = array([10])
X[I,:]

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


2
นี่เป็นการคัดลอกข้อมูลอาร์เรย์
ต่อ

นี่ไม่ใช่กรณีเสมอไป ดู: x = np.array([[1,2,3,4]]) ถ้าคุณหั่นมันด้วย x[[0],[1,2]] คุณจะได้รับมิติเดียว array([2, 3]) ความคิดเห็นของฉันคือเมื่อเลือกเวกเตอร์คอลัมน์หรือแถวควรทำให้ชิ้นเรียบง่ายแล้วใช้ np.reshapeดังนั้นในตัวอย่างของฉันมันจะเป็นnp.reshape(x[0,[1,2]],[1,2])
Alexander

1
คนอื่น ๆ ระวังอัฒภาคในท้ายที่สุด - เป็นสิ่งสำคัญX[[10]]จะถูกตีความว่าX[10]และรูปร่างจะเล็กลง ในทำนองเดียวกันX[[10, 20]] == X[10, 20]และรูปร่างก็เล็กลงด้วย
Ben Usman

1
คำเตือน : อย่าผสมผสานวิธีการจัดทำดัชนีนี้กับการสร้างดัชนีจำนวนเต็ม! หากคุณมีaรูปร่าง(10, 20, 30)ก็a[0, :, [0]]จะมีรูปร่าง(1, 20)ไม่ใช่(20, 1)เพราะในดัชนีหลังถูกถ่ายทอดa[[0], :, [0]]ซึ่งมักไม่เป็นไปตามที่คุณคาดหวัง! ในขณะที่a[0, :, :1]จะให้คุณ(20, 1)ตามที่คาดหวัง ยิ่งไปกว่านั้นดูความคิดเห็นด้านบนสำหรับเคสขอบแปลก ๆ ที่มีดัชนีเดียว โดยรวมแล้วดูเหมือนว่าวิธีนี้จะมีขอบมากเกินไป
Ben Usman

30

ฉันพบวิธีแก้ปัญหาที่สมเหตุสมผลสองสามข้อ

1) ใช้ numpy.take(X,[10],0)

2) ใช้การสร้างดัชนีที่แปลกประหลาดนี้ X[10:11:, :]

ตามหลักการแล้วควรเป็นค่าเริ่มต้น ฉันไม่เคยเข้าใจว่าทำไมมิติถึงหลุดออกไป แต่นั่นคือการอภิปรายสำหรับ numpy ...


2
"มิติ" จะถูกทิ้งเมื่อสร้างดัชนีรายการ Python alist[0]และเก็บไว้เมื่อหั่นเป็นชิ้นเล็กชิ้นน้อย
hpaulj

5
ตัวเลือกที่ 2 (ซึ่งสามารถเขียนเป็นslice(n, n+1)สำหรับการแยกดัชนีn) ควรเป็นคำตอบที่ยอมรับได้เนื่องจากเป็นคำตอบเดียวที่ขยายไปยังกรณี n มิติตามธรรมชาติ
norok2

ตัวเลือกที่ 2 ดูเหมือนจะสามารถเขียนได้X[10:11, :]ใน Python 3.7.5 (กล่าวคือไม่มีเครื่องหมายจุดคู่พิเศษหลัง 11)
โจ

7

นี่เป็นทางเลือกที่ฉันชอบดีกว่า แทนที่จะสร้างดัชนีด้วยตัวเลขเดียวให้สร้างดัชนีด้วยช่วง X[10:11,:]นั่นคือการใช้ (โปรดทราบว่า10:11ไม่รวม 11)

import numpy as np
X = np.zeros((100,10))
X.shape        # >> (100, 10)
xslice = X[10:11,:]
xslice.shape   # >> (1,10)

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

b = np.ones((2, 3, 4))
b.shape # >> (2, 3, 4)
b[1:2,:,:].shape  # >> (1, 3, 4)
b[:, 2:3, :].shape .  # >> (2, 1, 4)


0

สิ่งนี้น่ารำคาญอย่างยิ่งหากคุณกำลังสร้างดัชนีโดยอาร์เรย์ที่อาจมีความยาว 1 ในขณะรันไทม์ สำหรับกรณีนั้นมีnp.ix_:

some_array[np.ix_(row_index,column_index)]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.