อะไรคือความแตกต่างระหว่างฟังก์ชั่นการแบนและ ravel ในแบบ numpy?


292
import numpy as np
y = np.array(((1,2,3),(4,5,6),(7,8,9)))
OUTPUT:
print(y.flatten())
[1   2   3   4   5   6   7   8   9]
print(y.ravel())
[1   2   3   4   5   6   7   8   9]

ฟังก์ชั่นทั้งสองกลับรายการเดียวกัน แล้วความต้องการของสองฟังก์ชันที่แตกต่างกันคืออะไรที่ทำหน้าที่เดียวกัน


14
Ravel มักจะคืนค่ามุมมองไปยังอาร์เรย์ที่มีอยู่ (บางครั้งก็ส่งคืนสำเนา) แผ่แบนส่งกลับอาร์เรย์ใหม่
Alex

5
มีความเป็นไปได้ที่ซ้ำกันของความแบนและ ravel ต่างกันเป็นจำนวนเท่าไร
finnw

1
นี่คือการสาธิตการปฏิบัติที่แตกต่างกันเล็กน้อย
prosti

ดังนั้นใครบางคนสามารถให้ตัวอย่างเมื่อมันจะดีกว่าที่จะแผ่อาร์เรย์และเมื่อจะทำลายมัน?
Aleksandar

คำตอบ:


371

API ปัจจุบันคือ:

  • flatten ส่งคืนสำเนาเสมอ
  • ravelส่งคืนมุมมองของอาร์เรย์ดั้งเดิมเมื่อทำได้ สิ่งนี้ไม่สามารถมองเห็นได้ในผลลัพธ์ที่พิมพ์ แต่ถ้าคุณปรับเปลี่ยนอาร์เรย์ที่ส่งคืนโดย ravel มันอาจแก้ไขรายการในอาร์เรย์เดิม หากคุณแก้ไขรายการในอาเรย์ที่ส่งคืนจากการแบนจะไม่เกิดขึ้น บ่อยครั้งที่ ravel จะเร็วขึ้นเนื่องจากไม่มีการคัดลอกหน่วยความจำ แต่คุณต้องระมัดระวังในการปรับเปลี่ยนอาร์เรย์ที่ส่งคืน
  • reshape((-1,)) รับมุมมองเมื่อใดก็ตามที่ความก้าวหน้าของอาร์เรย์อนุญาตแม้ว่านั่นหมายความว่าคุณจะไม่ได้รับอาร์เรย์ที่ต่อเนื่องกันเสมอไป

30
ความคิดใด ๆ ที่นักพัฒนา NumPy ไม่ยึดติดกับฟังก์ชั่นเดียวกับการคัดลอกพารามิเตอร์ = [จริงเท็จ]?
Franck Dernoncourt

41
Backcompat รับประกันว่าบางครั้งสิ่งแปลก ๆ เช่นนี้จะเกิดขึ้น ตัวอย่างเช่น: นักพัฒนา numpy เมื่อเร็ว ๆ นี้ (ใน 1.10) เพิ่มการรับประกันโดยนัยก่อนหน้านี้ว่า ravel จะส่งคืนอาร์เรย์ที่ต่อเนื่องกัน (คุณสมบัติที่มีความสำคัญมากเมื่อเขียนส่วนขยาย C) ดังนั้นตอนนี้ API a.flatten()จะได้รับสำเนาแน่นอนa.ravel()เพื่อหลีกเลี่ยง สำเนาส่วนใหญ่ แต่ยังคงรับประกันว่าอาร์เรย์ที่ส่งคืนจะต่อเนื่องกันและa.reshape((-1,))รับมุมมองจริงๆเมื่อใดก็ตามที่ความก้าวหน้าของอาร์เรย์อนุญาตแม้ว่าจะหมายความว่าคุณจะไม่ได้รับอาร์เรย์ที่ต่อเนื่องกันเสมอไป
IanH

4
@Hossein IanH อธิบายว่า: ravelรับประกันอาเรย์ที่ต่อเนื่องกันดังนั้นจึงไม่รับประกันว่าจะส่งคืนมุมมอง reshapeส่งคืนมุมมองเสมอและดังนั้นจึงไม่รับประกันว่าจะส่งคืนอาร์เรย์ที่ต่อเนื่องกัน
ILED

4
@ โฮเซ่นั่นจะเป็นคำถามใหม่ทั้งหมด สั้น ๆ มันเร็วกว่ามากในการอ่านและเขียนไปยังพื้นที่หน่วยความจำต่อเนื่อง มีคำถามและคำตอบมากมายเกี่ยวกับที่นี่ใน SO ( ตัวอย่างที่ดีที่นี่ ) อย่าลังเลที่จะเปิดคำถามใหม่หากคุณมีคำถามเพิ่มเติม
ILED

2
reshape(-1)เทียบเท่ากับreshape((-1,))
Tom Pohl

53

ตามที่อธิบายไว้ที่นี่ข้อแตกต่างที่สำคัญคือ:

  • flatten เป็นวิธีการของวัตถุ ndarray และด้วยเหตุนี้จึงสามารถเรียกเฉพาะอาร์เรย์ numpy ที่แท้จริง

  • ravel เป็นฟังก์ชั่นระดับห้องสมุดและด้วยเหตุนี้จึงสามารถเรียกใช้บนวัตถุใด ๆ ที่สามารถแยกวิเคราะห์ได้สำเร็จ

ตัวอย่างเช่นravelจะทำงานกับรายการของ ndarrays ในขณะที่flattenไม่พร้อมใช้งานสำหรับวัตถุชนิดนั้น

@IanH ยังชี้ให้เห็นความแตกต่างที่สำคัญกับการจัดการหน่วยความจำในคำตอบของเขา


4
ขอบคุณสำหรับข้อมูลเกี่ยวกับ ravel () ที่ทำงานในรายการของndarray's
javadba

ไม่เพียง แต่รายการของอาร์เรย์ แต่ยังแสดงรายการ :)
timtody

15

นี่คือเนมสเปซที่ถูกต้องสำหรับฟังก์ชั่น:

ทั้งสองฟังก์ชั่นคืนค่าอาร์เรย์ 1D แบบแบนซึ่งชี้ไปยังโครงสร้างหน่วยความจำใหม่

import numpy
a = numpy.array([[1,2],[3,4]])

r = numpy.ravel(a)
f = numpy.ndarray.flatten(a)  

print(id(a))
print(id(r))
print(id(f))

print(r)
print(f)

print("\nbase r:", r.base)
print("\nbase f:", f.base)

---returns---
140541099429760
140541099471056
140541099473216

[1 2 3 4]
[1 2 3 4]

base r: [[1 2]
 [3 4]]

base f: None

ในตัวอย่างด้านบน:

  • ตำแหน่งหน่วยความจำของผลลัพธ์นั้นแตกต่างกัน
  • ผลลัพธ์มีลักษณะเหมือนกัน
  • แบนจะส่งคืนสำเนา
  • ravel จะส่งคืนมุมมอง

เราจะตรวจสอบว่ามีสิ่งใดเป็นสำเนาได้หรือไม่ การใช้แอตทริบิวต์ของ.base ndarrayถ้าเป็นมุมมองฐานจะเป็นอาร์เรย์ดั้งเดิม Noneถ้ามันเป็นสำเนาฐานจะเป็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.