6.12. การเลือกและการจัดเรียงใหม่¶
การลดค่ายุบอาร์เรย์ให้เป็นสเกลาร์หรือผลลัพธ์ที่มีอันดับต่ำกว่า การเลือกครอบคลุมการดำเนินการที่เลือกว่าสมาชิก ใด จะรอดและ ไปอยู่ที่ใด: การเลือกตามเงื่อนไข การตัดค่า การเรียงลำดับ การค้นหาดัชนี และการจัดเรียงใหม่ตามแกน
6.12.1. การเลือกตามเงื่อนไข¶
where() คืนอาร์เรย์ที่รับสมาชิกจาก x ณ ตำแหน่งที่เงื่อนไขเป็นจริง และจาก y ในกรณีอื่น ตัวถูกดำเนินการสามตัวบรอดแคสต์ร่วมกัน:
a = np.array([1, 2, 3, 4, 5], dtype=np.float)
np.where(a < 3, a, 0.0)
# array([1.0, 2.0, 0.0, 0.0, 0.0])
นี่คือเครื่องมือที่เหมาะสำหรับ "if/else ทุกสมาชิก" โดยไม่ต้องเขียนลูป Python
clip() เป็นตัวย่อของ maximum(lo, minimum(a, hi)) -- ตัดค่าให้อยู่ในช่วง:
np.clip(a, 2.0, 4.0)
# array([2.0, 2.0, 3.0, 4.0, 4.0])
maximum() และ minimum() รับตัวถูกดำเนินการสองตัวและคืนค่ามากกว่า / น้อยกว่าแบบ element-wise:
np.maximum(a, 3.0)
np.minimum(a, np.array([5, 4, 3, 2, 1]))
6.12.2. การค้นหาดัชนี¶
nonzero() คืนพิกัดของทุกสมาชิกที่ไม่ใช่ศูนย์ แยกเป็นอาร์เรย์ดัชนีหนึ่งชุดต่อมิติ สำหรับอินพุต 2 มิติ ผลลัพธ์เป็น tuple ของอาร์เรย์สองชุด: ชุดแรกเก็บดัชนีแถว ชุดที่สองเก็บดัชนีคอลัมน์ การจับคู่ทั้งสองตามแนวคอลัมน์จะได้ตำแหน่ง (row, col) ของแต่ละตำแหน่งที่ไม่ใช่ศูนย์:
m = np.array([[0, 2, 0],
[3, 0, 0]], dtype=np.float)
np.nonzero(m)
# (array([0, 1], dtype=uint16), array([1, 0], dtype=uint16))
สมาชิกที่ไม่ใช่ศูนย์ใน m คือ m[0, 1] = 2 และ m[1, 0] = 3 อาร์เรย์แรกที่คืนมา [0, 1] ให้ดัชนีแถวของทั้งสอง ส่วนอาร์เรย์ที่สอง [1, 0] ให้ดัชนีคอลัมน์ การอ่านอาร์เรย์ทั้งสองควบคู่กันจะกู้คืนตำแหน่ง (0, 1) และ (1, 0)
การลดค่าสองรูปแบบยังให้ดัชนีด้วย:
argmin()/argmax()-- ดัชนีของสมาชิกที่น้อยที่สุด / มากที่สุดargsort()-- อาร์เรย์จำนวนเต็มที่จะเรียงลำดับอินพุตตามแกนที่กำหนด (ค่าเริ่มต้นคือแกนสุดท้าย):a = np.array([40, 10, 30, 20], dtype=np.uint8) idx = np.argsort(a) # array([1, 3, 2, 0], dtype=uint16) a[idx] # array([10, 20, 30, 40])
argsortคืนค่าuint16เสมอ ดังนั้นอาร์เรย์ที่ถูกเรียงลำดับต้องมีไม่เกิน 65,535 สมาชิกบนแกนที่เรียง
bincount() นับการเกิดขึ้นของแต่ละจำนวนเต็มที่ไม่ติดลบในอินพุต uint8 / uint16 แบบ 1-D:
histogram = np.bincount(np.array([0, 1, 1, 2, 2, 2], dtype=np.uint8))
# array([1, 2, 3], dtype=uint16)
มีประโยชน์สำหรับสร้างฮิสโตแกรมของค่าพิกเซลจำนวนเต็มเล็กโดยไม่ต้องเขียนลูป Python
6.12.3. การเรียงลำดับและการจัดเรียงใหม่¶
sort() คืนสำเนาที่เรียงลำดับแล้วของอาร์เรย์ตามแกนที่กำหนด (แกนสุดท้ายเป็นค่าเริ่มต้น) ใช้ sort() บนอาร์เรย์โดยตรงสำหรับการเรียงลำดับ in-place:
np.sort(np.array([3, 1, 2], dtype=np.float))
# array([1.0, 2.0, 3.0])
flip() กลับลำดับตามแกนที่กำหนด (ทุกแกนเมื่อไม่ได้ระบุ axis):
np.flip(np.array([1, 2, 3, 4]))
# array([4, 3, 2, 1])
roll() เลื่อนสมาชิกแบบวงกลมตามจำนวนที่กำหนด มีประโยชน์สำหรับการใช้งาน shift register แบบ ring-buffer:
np.roll(np.array([1, 2, 3, 4]), 1)
# array([4, 1, 2, 3])
take() เป็นรูปแบบชัดเจนของ fancy indexing -- เลือกสมาชิกที่ดัชนีที่กำหนด:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.take(a, [0, 2, 4])
# array([10, 30, 50], dtype=uint8)
6.12.4. การกรองและการแก้ไขโครงสร้าง¶
compress() เป็นรูปแบบชัดเจนของ boolean indexing -- คืนชิ้นส่วนของ a ที่เลือกโดยเงื่อนไขบูลีน:
a = np.array([10, 20, 30, 40], dtype=np.uint8)
np.compress(a > 15, a)
# array([20, 30, 40], dtype=uint8)
delete() คืนสำเนาโดยลบรายการที่ดัชนีที่กำหนดออก:
a = np.array([10, 20, 30, 40, 50], dtype=np.uint8)
np.delete(a, [1, 3])
# array([10, 30, 50], dtype=uint8)
diff() คืนผลต่างไปข้างหน้าลำดับที่ n ของอาร์เรย์ตามแกน ใช้สำหรับคำนวณการเปลี่ยนแปลงอันดับหนึ่งระหว่างตัวอย่างที่ติดกัน:
samples = np.array([1, 3, 6, 10, 15], dtype=np.float)
np.diff(samples)
# array([2.0, 3.0, 4.0, 5.0])
6.12.5. ต้นทุนของแต่ละการดำเนินการ¶
ฟังก์ชันเกือบทุกฟังก์ชันในหน้านี้คืนอาร์เรย์ที่จัดสรรใหม่ มีข้อยกเว้นสองกรณี:
sort()เรียงลำดับ in-place ส่วนฟังก์ชันsort()คืนสำเนาที่เรียงลำดับแล้วtake()รับคีย์เวิร์ดout=เพื่อเขียนลงในบัฟเฟอร์ที่มีอยู่แล้ว
ในลูปที่รันหลายครั้งต่อวินาที ควรใช้ sort() แบบ in-place และนำบัฟเฟอร์ที่จัดสรรล่วงหน้ากลับมาใช้ซ้ำทุกที่ มาสก์บูลีนเองถูกจัดสรรทุกครั้งที่การเปรียบเทียบทำงาน -- สร้างมาสก์ครั้งเดียวและนำกลับมาใช้ซ้ำข้ามการดำเนินการแทนที่จะสร้างใหม่ในทุกรอบ