ดูบนอาร์เรย์ numpy?


92

ฉันมีnumpyอาร์เรย์2D มีวิธีสร้างมุมมองที่จะรวมkแถวแรกและคอลัมน์ทั้งหมดหรือไม่

ประเด็นคือหลีกเลี่ยงการคัดลอกข้อมูลพื้นฐาน (อาร์เรย์มีขนาดใหญ่มากจนไม่สามารถทำสำเนาบางส่วนได้)

คำตอบ:


232

แน่นอนเพียงจัดทำดัชนีตามปกติ เช่นy = x[:k, :] สิ่งนี้จะส่งคืนมุมมองไปยังอาร์เรย์เดิม จะไม่มีการคัดลอกข้อมูลและการอัปเดตใด ๆ ที่เกิดขึ้นyจะมีผลในxทางกลับกัน


แก้ไข:

ฉันมักจะทำงานกับอาร์เรย์ 3D> 10GB ของ uint8 ดังนั้นฉันจึงกังวลเกี่ยวกับเรื่องนี้มาก ... Numpy สามารถจัดการหน่วยความจำได้อย่างมีประสิทธิภาพหากคุณคำนึงถึงบางสิ่ง เคล็ดลับบางประการในการหลีกเลี่ยงการทำสำเนาอาร์เรย์ในหน่วยความจำมีดังนี้

การใช้งาน+=, -=, *=ฯลฯ เพื่อหลีกเลี่ยงการทำสำเนาของอาร์เรย์ เช่นx += 10จะแก้ไขอาร์เรย์ในขณะที่x = x + 10จะทำสำเนาและแก้ไข (ดูnumexpr ด้วย )

หากคุณต้องการทำสำเนาด้วยx = x + 10โปรดทราบว่าx = x + 10.0จะxถูกอัพไปยังอาร์เรย์ทศนิยมโดยอัตโนมัติหากยังไม่ได้ทำ แต่x += 10.0ที่xเป็นอาร์เรย์จำนวนเต็มจะทำให้เกิดการ10.0ที่จะลงไปหล่อ int ของความแม่นยำเช่นเดียวกับอาร์เรย์แทน

นอกจากนี้ฟังก์ชัน numpy จำนวนมากยังใช้outพารามิเตอร์ดังนั้นคุณสามารถทำสิ่งต่างๆได้เช่นnp.abs(x, x)หาค่าสัมบูรณ์ของxin-place


ในการแก้ไขครั้งที่สองต่อไปนี้เป็นเคล็ดลับเพิ่มเติมเกี่ยวกับมุมมองเทียบกับสำเนาที่มีอาร์เรย์ numpy:

ไม่เหมือนกับรายการ python y = x[:]ไม่ส่งคืนสำเนา แต่จะส่งคืนมุมมอง หากคุณต้องการสำเนา (ซึ่งแน่นอนว่าจะเพิ่มจำนวนหน่วยความจำที่คุณใช้เป็นสองเท่า) ใช้y = x.copy()

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

ดังตัวอย่างนี้: y = x[[0, 1, 2], :]ส่งคืนสำเนาในขณะที่y = x[:3,:]จะส่งคืนมุมมอง

แม้แต่การจัดทำดัชนีที่บ้าคลั่งจริงๆก็เหมือนกับการจัดทำดัชนีx[4:100:5, :-10:-1, None]"ปกติ" และจะส่งคืนมุมมองดังนั้นอย่ากลัวที่จะใช้เทคนิคการแบ่งส่วนต่างๆในอาร์เรย์ขนาดใหญ่

x.astype(<dtype>)จะส่งคืนสำเนาของข้อมูลเป็นประเภทใหม่ในขณะที่x.view(<dtype>)จะส่งคืนมุมมอง

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

ตัวอย่างเช่นหมายความว่า1.0เมื่อลอย 64 บิตบนระบบ little-endian จะถูก4607182418800017408มองเป็น 64 บิต int และอาร์เรย์ของ[ 0, 0, 0, 0, 0, 0, 240, 63]ถ้าถูกมองว่าเป็น uint8 นี่เป็นสิ่งที่ดีจริงๆเมื่อคุณต้องการทำการเรียงลำดับบิตบนอาร์เรย์ขนาดใหญ่แม้ว่า ... คุณจะมีการควบคุมระดับต่ำในการตีความบัฟเฟอร์หน่วยความจำ


ขอบคุณสำหรับคำแนะนำที่ดีมาก! ผมอ่านคู่มือผู้ใช้ Numpy และสับสนว่าทำไมการแก้ไขx[np.array([1, 1, 3, 1])] += 1 xได้แล้ว!
tnq177

เคล็ดลับดีๆ! ฉันมีคำถามอื่น จะพิสูจน์ได้อย่างไรว่า numpy ไม่ได้เรียกสำเนา แต่เป็นเพียงมุมมอง ดูเหมือนว่า id () ของ python จะใช้ไม่ได้
wuhaochi

3
@wuhaochi ถ้าbเป็นวิวaแล้วb.base is aจะเป็นTrue. สำเนา (ของอาร์เรย์ใด ๆ ) จะมีเสมอarr_copy.base is None
Jürg Merlin Spaak
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.