Sự khác biệt giữa chức năng flatten và ravel trong numpy là gì?


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]

Cả hai hàm trả về cùng một danh sách. Vậy thì nhu cầu của hai chức năng khác nhau thực hiện cùng một công việc là gì.


14
Ravel thường trả về một khung nhìn vào mảng hiện có (đôi khi nó trả về một bản sao). Flatten trả về một mảng mới.
Alex


1
Dưới đây là một minh chứng thực tế của sự khác biệt tinh tế.
prosti

Vì vậy, ai đó có thể đưa ra một ví dụ khi tốt hơn là làm phẳng một mảng và khi nào thì nó?
Alexanderar

Câu trả lời:


371

API hiện tại là:

  • flatten luôn trả về một bản sao.
  • raveltrả về một cái nhìn của mảng ban đầu bất cứ khi nào có thể. Điều này không hiển thị trong đầu ra được in, nhưng nếu bạn sửa đổi mảng được trả về bởi ravel, nó có thể sửa đổi các mục trong mảng ban đầu. Nếu bạn sửa đổi các mục trong một mảng được trả về từ làm phẳng thì điều này sẽ không bao giờ xảy ra. Ravel thường sẽ nhanh hơn vì không có bộ nhớ được sao chép, nhưng bạn phải cẩn thận hơn về việc sửa đổi mảng mà nó trả về.
  • reshape((-1,)) có được một khung nhìn bất cứ khi nào các bước của mảng cho phép nó ngay cả khi điều đó có nghĩa là bạn không luôn luôn có được một mảng liền kề.

30
Có ai biết tại sao các nhà phát triển NumPy không gắn bó với một chức năng với một số tham số sao chép = [Đúng, Sai] không?
Franck Dernoncourt

41
Backcompat đảm bảo đôi khi gây ra những điều kỳ lạ như thế này xảy ra. Ví dụ: các nhà phát triển numpy gần đây (trong 1.10) đã thêm một đảm bảo ngầm trước đó rằng ravel sẽ trả về một mảng liền kề (một thuộc tính rất quan trọng khi viết các phần mở rộng C), vì vậy bây giờ API a.flatten()phải lấy một bản sao để chắc chắn, a.ravel()để tránh hầu hết các bản sao nhưng vẫn đảm bảo rằng mảng được trả về là liền kề và a.reshape((-1,))để thực sự có được chế độ xem bất cứ khi nào các bước của mảng cho phép ngay cả khi điều đó có nghĩa là bạn không luôn nhận được một mảng liền kề.
IanH

4
@Hossein IanH giải thích nó: ravelđảm bảo một mảng liền kề, và do đó không đảm bảo rằng nó trả về một khung nhìn; reshapeluôn trả về một khung nhìn và do đó không đảm bảo rằng nó trả về một mảng liền kề.
iled

4
@Hossein Đó sẽ là một câu hỏi hoàn toàn mới. Rất ngắn gọn, nó nhanh hơn nhiều để đọc và ghi vào một không gian bộ nhớ liền kề. Có một số câu hỏi và câu trả lời về điều đó ở đây trên SO ( ví dụ hay ở đây ), vui lòng mở một câu hỏi mới nếu bạn có bất kỳ câu hỏi nào khác.
iled

2
reshape(-1)tương đương vớireshape((-1,))
Tom Pohl

53

Như đã giải thích ở đây, một điểm khác biệt chính là:

  • flatten là một phương thức của một đối tượng ndarray và do đó chỉ có thể được gọi cho các mảng numpy thực sự.

  • ravel là một hàm cấp thư viện và do đó có thể được gọi trên bất kỳ đối tượng nào có thể được phân tích cú pháp thành công.

Ví dụ ravelsẽ hoạt động trên một danh sách các ndarrays, trong khi flattenkhông có sẵn cho loại đối tượng đó.

@IanH cũng chỉ ra những khác biệt quan trọng trong việc xử lý bộ nhớ trong câu trả lời của anh ấy.


4
thx cho rằng thông tin về Ravel () làm việc trên danh sách ndarray's
javadba

Không chỉ danh sách các mảng mà còn cả danh sách các danh sách :)
timtody

15

Đây là không gian tên chính xác cho các chức năng:

Cả hai hàm đều trả về các mảng 1D dẹt chỉ vào các cấu trúc bộ nhớ mới.

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

Trong ví dụ trên:

  • vị trí bộ nhớ của kết quả là khác nhau,
  • kết quả trông giống nhau
  • flatten sẽ trả lại một bản sao
  • Ravel sẽ trả lại một cái nhìn.

Làm thế nào chúng ta kiểm tra nếu một cái gì đó là một bản sao? Sử dụng .basethuộc tính của ndarray. Nếu đó là một khung nhìn, cơ sở sẽ là mảng ban đầu; nếu nó là một bản sao, cơ sở sẽ được None.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.