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 และนำบัฟเฟอร์ที่จัดสรรล่วงหน้ากลับมาใช้ซ้ำทุกที่ มาสก์บูลีนเองถูกจัดสรรทุกครั้งที่การเปรียบเทียบทำงาน -- สร้างมาสก์ครั้งเดียวและนำกลับมาใช้ซ้ำข้ามการดำเนินการแทนที่จะสร้างใหม่ในทุกรอบ