สมมติว่าฉันมี:
test = numpy.array([[1, 2], [3, 4], [5, 6]])
test[i]
ได้รับฉันithบรรทัดของอาร์เรย์ (เช่น[1, 2]
) ฉันจะเข้าถึงคอลัมน์ith ได้อย่างไร (เช่น[1, 3, 5]
) นอกจากนี้สิ่งนี้จะเป็นการดำเนินการที่มีราคาแพงหรือไม่
สมมติว่าฉันมี:
test = numpy.array([[1, 2], [3, 4], [5, 6]])
test[i]
ได้รับฉันithบรรทัดของอาร์เรย์ (เช่น[1, 2]
) ฉันจะเข้าถึงคอลัมน์ith ได้อย่างไร (เช่น[1, 3, 5]
) นอกจากนี้สิ่งนี้จะเป็นการดำเนินการที่มีราคาแพงหรือไม่
คำตอบ:
>>> test[:,0]
array([1, 3, 5])
ในทำนองเดียวกัน
>>> test[1,:]
array([3, 4])
ช่วยให้คุณเข้าถึงแถว นี้จะครอบคลุมในข้อ 1.4 (ดัชนี) ของการอ้างอิง NumPy อย่างรวดเร็วอย่างน้อยก็ในประสบการณ์ของฉัน แน่นอนว่าเร็วกว่าการเข้าถึงแต่ละองค์ประกอบในลูป
และถ้าคุณต้องการเข้าถึงมากกว่าหนึ่งคอลัมน์ในเวลาที่คุณสามารถทำได้:
>>> test = np.arange(9).reshape((3,3))
>>> test
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> test[:,[0,2]]
array([[0, 2],
[3, 5],
[6, 8]])
test[:,[0,2]]
เพียงแค่เข้าถึงข้อมูลเช่นtest[:, [0,2]] = something
จะแก้ไขการทดสอบและไม่สร้างอาร์เรย์อื่น แต่copy_test = test[:, [0,2]]
จริง ๆ แล้วสร้างสำเนาตามที่คุณพูด
test[:,[0,2]]
เข้าถึงข้อมูลในขณะที่test[:, [0, 2]][:, [0, 1]]
ไม่? ดูเหมือนว่าใช้งานง่ายมากที่ทำสิ่งเดียวกันอีกครั้งมีผลที่แตกต่างกัน
>>> test[:,0]
array([1, 3, 5])
คำสั่งนี้ให้เวกเตอร์แถวกับคุณ, ถ้าคุณแค่อยากวนรอบมัน, ก็โอเค, แต่ถ้าคุณต้องการ hstack กับอาเรย์อื่นที่มีขนาด 3xN, คุณจะได้
ValueError: all the input arrays must have same number of dimensions
ในขณะที่
>>> test[:,[0]]
array([[1],
[3],
[5]])
ให้เวกเตอร์คอลัมน์แก่คุณเพื่อให้คุณสามารถดำเนินการต่อกันหรือ hstack
เช่น
>>> np.hstack((test, test[:,[0]]))
array([[1, 2, 1],
[3, 4, 3],
[5, 6, 5]])
คุณสามารถเปลี่ยนตำแหน่งและส่งคืนแถวได้ด้วย:
In [4]: test.T[0]
Out[4]: array([1, 3, 5])
หากต้องการรับคอลัมน์ที่หลากหลายและเป็นอิสระเพียง:
> test[:,[0,2]]
คุณจะได้รับ colums 0 และ 2
แม้ว่าคำถามจะได้รับคำตอบให้ฉันพูดถึงความแตกต่างบางอย่าง
สมมติว่าคุณสนใจคอลัมน์แรกของอาร์เรย์
arr = numpy.array([[1, 2],
[3, 4],
[5, 6]])
ดังที่คุณทราบจากคำตอบอื่น ๆ แล้วเพื่อให้ได้ในรูปแบบของ "row vector" (อาร์เรย์ของรูปร่าง(3,)
) คุณใช้การแบ่งส่วน:
arr_c1_ref = arr[:, 1] # creates a reference to the 1st column of the arr
arr_c1_copy = arr[:, 1].copy() # creates a copy of the 1st column of the arr
ในการตรวจสอบว่าอาร์เรย์เป็นมุมมองหรือสำเนาของอาร์เรย์อื่นคุณสามารถทำสิ่งต่อไปนี้:
arr_c1_ref.base is arr # True
arr_c1_copy.base is arr # False
นอกเหนือจากความแตกต่างที่เห็นได้ชัดระหว่างสอง (การแก้ไขarr_c1_ref
จะมีผลต่อarr
) จำนวนของขั้นตอนไบต์สำหรับการสำรวจแต่ละครั้งจะแตกต่างกัน:
arr_c1_ref.strides[0] # 8 bytes
arr_c1_copy.strides[0] # 4 bytes
ดูความก้าวหน้า ทำไมสิ่งนี้จึงสำคัญ ลองนึกภาพว่าคุณมีอาร์เรย์ที่ใหญ่มากA
แทนที่จะเป็นarr
:
A = np.random.randint(2, size=(10000,10000), dtype='int32')
A_c1_ref = A[:, 1]
A_c1_copy = A[:, 1].copy()
และคุณต้องการที่จะคำนวณผลรวมของทุกองค์ประกอบของคอลัมน์แรกคือหรือA_c1_ref.sum()
A_c1_copy.sum()
การใช้เวอร์ชันที่คัดลอกนั้นเร็วกว่ามาก:
%timeit A_c1_ref.sum() # ~248 µs
%timeit A_c1_copy.sum() # ~12.8 µs
นี่เป็นเพราะจำนวนก้าวที่แตกต่างกันที่กล่าวถึงก่อนหน้า:
A_c1_ref.strides[0] # 40000 bytes
A_c1_copy.strides[0] # 4 bytes
แม้ว่าอาจดูเหมือนว่าการใช้การคัดลอกคอลัมน์นั้นดีกว่า แต่ก็ไม่จริงเสมอไปสำหรับเหตุผลที่การทำสำเนาต้องใช้เวลาและใช้หน่วยความจำเพิ่มขึ้น (ในกรณีนี้มันใช้เวลาประมาณ 200 approxs ในการสร้างA_c1_copy
) อย่างไรก็ตามถ้าเราต้องการสำเนาในตอนแรกหรือเราต้องทำการดำเนินการต่าง ๆ ในคอลัมน์เฉพาะของอาร์เรย์และเราก็โอเคกับการเสียสละหน่วยความจำสำหรับความเร็วแล้วการทำสำเนาเป็นวิธีที่จะไป
ในกรณีที่เราสนใจที่จะทำงานกับคอลัมน์เป็นส่วนใหญ่มันอาจเป็นความคิดที่ดีที่จะสร้างอาเรย์ของเราในลำดับของคอลัมน์หลัก ('F') แทนลำดับของแถวหลัก ('C') (ซึ่งเป็นค่าเริ่มต้น ) จากนั้นทำการแบ่งตามเดิมเพื่อรับคอลัมน์โดยไม่คัดลอก:
A = np.asfortranarray(A) # or np.array(A, order='F')
A_c1_ref = A[:, 1]
A_c1_ref.strides[0] # 4 bytes
%timeit A_c1_ref.sum() # ~12.6 µs vs ~248 µs
ตอนนี้การดำเนินการรวม (หรืออื่น ๆ ) ในมุมมองคอลัมน์จะเร็วขึ้นมาก
ในที่สุดขอให้ฉันทราบว่าการย้ายอาเรย์และการใช้การแบ่งแถวนั้นเหมือนกับการใช้การแบ่งคอลัมน์ในอาเรย์ดั้งเดิมเนื่องจากการย้ายจะทำโดยการสลับรูปร่างและความก้าวหน้าของอาเรย์เดิม
A.T[1,:].strides[0] # 40000
>>> test
array([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]])
>>> ncol = test.shape[1]
>>> ncol
5L
จากนั้นคุณสามารถเลือกคอลัมน์ที่ 2 - 4 ด้วยวิธีนี้:
>>> test[0:, 1:(ncol - 1)]
array([[1, 2, 3],
[6, 7, 8]])