ฉันมีnumpy
อาร์เรย์2D มีวิธีสร้างมุมมองที่จะรวมk
แถวแรกและคอลัมน์ทั้งหมดหรือไม่
ประเด็นคือหลีกเลี่ยงการคัดลอกข้อมูลพื้นฐาน (อาร์เรย์มีขนาดใหญ่มากจนไม่สามารถทำสำเนาบางส่วนได้)
ฉันมีnumpy
อาร์เรย์2D มีวิธีสร้างมุมมองที่จะรวมk
แถวแรกและคอลัมน์ทั้งหมดหรือไม่
ประเด็นคือหลีกเลี่ยงการคัดลอกข้อมูลพื้นฐาน (อาร์เรย์มีขนาดใหญ่มากจนไม่สามารถทำสำเนาบางส่วนได้)
คำตอบ:
แน่นอนเพียงจัดทำดัชนีตามปกติ เช่น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)
หาค่าสัมบูรณ์ของx
in-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 นี่เป็นสิ่งที่ดีจริงๆเมื่อคุณต้องการทำการเรียงลำดับบิตบนอาร์เรย์ขนาดใหญ่แม้ว่า ... คุณจะมีการควบคุมระดับต่ำในการตีความบัฟเฟอร์หน่วยความจำ
b
เป็นวิวa
แล้วb.base is a
จะเป็นTrue
. สำเนา (ของอาร์เรย์ใด ๆ ) จะมีเสมอarr_copy.base is None
x[np.array([1, 1, 3, 1])] += 1
x
ได้แล้ว!