Яка різниця між сплющуваними та розгубленими функціями у нумері?


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 зазвичай повертає перегляд у існуючий масив (іноді він повертає копію). Flatten повертає новий масив.
Алекс


1
Ось практична демонстрація тонкої різниці.
prosti

То чи може хтось навести приклад, коли краще згладити масив і коли його згорнути?
Олександр

Відповіді:


371

Поточний API полягає в тому, що:

  • flatten завжди повертає копію.
  • ravelповертає перегляд вихідного масиву, коли це можливо. Це не видно у друкованому виході, але якщо ви модифікуєте масив, повернутий ravel, він може змінювати записи в початковому масиві. Якщо ви модифікуєте записи в масиві, поверненому з flatten, це ніколи не відбудеться. ravel часто буде швидше, оскільки жодна пам'ять не копіюється, але ви повинні бути більш уважними щодо зміни масиву, який він повертає.
  • reshape((-1,)) отримує перегляд, коли кроки масиву дозволяють йому, навіть якщо це означає, що ви не завжди отримуєте суміжний масив.

30
Будь-яка ідея, чому розробники NumPy не дотримувались однієї функції з деяким параметром copy = [True, False]?
Франк Дернонкурт

41
Гарантії зворотного зв'язку іноді викликають подібні випадки. Наприклад: нещодавно розробники numpy (в 1.10) додали попередньо неявну гарантію того, що ravel поверне суміжний масив (властивість, що дуже важливо при написанні розширень C), тому тепер API a.flatten()повинен отримати копію точно, a.ravel()щоб уникнути більшість копій, але все ж гарантують, що повернутий масив є суміжним, і a.reshape((-1,))реально отримувати перегляд, коли кроки масиву дозволяють йому, навіть якщо це означає, що ви не завжди отримуєте суміжний масив.
Ян

4
@Hossein IanH пояснив це: ravelгарантує суміжний масив, і тому не гарантується, що він поверне погляд; reshapeзавжди повертає вигляд, і тому не гарантується, що він повертає суміжний масив.
iled

4
@Hossein Це було б зовсім новим питанням. Коротше кажучи, набагато швидше читати та записувати у суміжний простір пам’яті. Є кілька запитань і відповідей на те, що тут на SO ( хороший приклад тут ), сміливо відкривайте нове, якщо у вас є додаткові запитання.
Iled

2
reshape(-1)еквівалентноreshape((-1,))
Том Поль

53

Як пояснено тут, ключова відмінність полягає в тому, що:

  • flatten є методом ndarray-об'єкта, і тому його можна викликати лише для справжніх масивів numpy.

  • ravel - це функція рівня бібліотеки, і тому її можна викликати будь-яким об'єктом, який можна успішно проаналізувати.

Наприклад, ravelбуде працювати над списком ndarrays, але flattenвін недоступний для цього типу об’єктів.

@IanH також вказує на важливі відмінності в обробці пам'яті у своїй відповіді.


4
THX для цієї інформації про 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

У верхньому прикладі:

  • місця пам'яті результатів різні,
  • результати виглядають однаково
  • flatten поверне копію
  • ravel поверне погляд.

Як ми перевіряємо, чи є щось копія? Використовуючи .baseатрибут ndarray. Якщо це вид, основою буде оригінальний масив; якщо це копія, база буде None.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.