В чем разница между функциями flatten и ravel в numpy?

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]

Обе функции возвращают один и тот же список. Тогда зачем нужны две разные функции, выполняющие одну и ту же работу.


person cryptomanic    schedule 08.03.2015    source источник
comment
Ravel обычно возвращает представление в существующий массив (иногда возвращает копию). Flatten возвращает новый массив.   -  person Alex    schedule 08.03.2015
comment
Возможный дубликат В чем разница между сглаживанием и расплыванием numpy?   -  person finnw    schedule 22.08.2016
comment
Здесь практическая демонстрация тонкой разницы.   -  person prosti    schedule 22.01.2019
comment
Так может ли кто-нибудь привести пример, когда лучше сгладить массив, а когда его растопить?   -  person Aleksandar    schedule 28.03.2020
comment
Спасибо, что задали этот вопрос, у меня был такой же вопрос.   -  person AndreiToroplean    schedule 12.10.2020


Ответы (3)


Текущий API таков:

  • flatten всегда возвращает копию.
  • ravel по возможности возвращает представление исходного массива. Это не видно в печатном выводе, но если вы измените массив, возвращаемый ravel, он может изменить записи в исходном массиве. Если вы измените записи в массиве, возвращаемом из flatten, этого никогда не произойдет. ravel часто будет быстрее, поскольку память не копируется, но вы должны быть более осторожны с изменением массива, который он возвращает.
  • reshape((-1,)) получает представление, когда позволяют шаги массива это даже если это означает, что вы не всегда получаете непрерывный массив.
person IanH    schedule 08.03.2015
comment
Есть идеи, почему разработчики NumPy не придерживались одной функции с некоторым параметром copy = [True, False]? - person Franck Dernoncourt; 17.11.2015
comment
@FranckDernoncourt Отличный вопрос. Я понятия не имею. Единственная причина, по которой я могу думать, - это желание предоставить простой аналог аналогичной команды Matlab. Похоже, что у него нет прецедента в numarray или numeric. - person IanH; 17.11.2015
comment
Гарантии обратной совместимости иногда вызывают подобные странные вещи. Например: разработчики numpy недавно (в 1.10) добавили ранее неявную гарантию того, что ravel вернет непрерывный массив (свойство, которое очень важно при написании расширений C), поэтому теперь API a.flatten(), чтобы получить копию наверняка, a.ravel() чтобы избежать большинства копий, но при этом гарантировать, что возвращаемый массив является непрерывным, и a.reshape((-1,)), чтобы действительно получить представление, когда это позволяют шаги массива, даже если это означает, что вы не всегда получаете непрерывный массив. - person IanH; 17.11.2015
comment
@IanH: В чем тогда разница между ravel и reshape? - person Rika; 07.01.2017
comment
@Hossein IanH объяснил это: ravel гарантирует непрерывный массив, поэтому не гарантируется, что он вернет представление; reshape всегда возвращает представление, поэтому не гарантируется, что оно вернет непрерывный массив. - person iled; 10.02.2017
comment
@iled: Спасибо, тогда что такого важного в непрерывности? почему я должен заботиться об этом? - person Rika; 10.02.2017
comment
@Hossein Это был бы совершенно новый вопрос. Вкратце, гораздо быстрее читать и писать в непрерывную область памяти. Здесь, на SO, есть несколько вопросов и ответов (хороший пример здесь) , не стесняйтесь открывать новый, если у вас возникнут дополнительные вопросы. - person iled; 10.02.2017
comment
reshape(-1) эквивалентно reshape((-1,)) - person Tom Pohl; 06.10.2017
comment
@diraria, мы обнаруживаем, что можем также передавать порядок в методе ravel. Если это «C», который является порядком по умолчанию, то возвращается вид исходного массива. Если 'F', то это скопированная версия массива, т.е. модификация в этом массиве не отражается в фактическом массиве. (Не уверен, что это особенность или ошибка: D) - person Shiv Krishna Jaiswal; 03.11.2018
comment
Обновление: просмотр исходного массива невозможен, если порядок равен 'F' в функции ravel. github.com / numpy / numpy / issues / 12318 - person Shiv Krishna Jaiswal; 03.11.2018
comment
Почему это называется ravel? В чем идея названия? - person off99555; 26.01.2019
comment
Как показывают эти обсуждения, Numpy великолепен, но не идеален. - person Julek; 30.05.2021

Как объяснено здесь, ключевое отличие состоит в том, что:

  • flatten - это метод объекта ndarray и, следовательно, может вызываться только для истинных массивов numpy.

  • ravel - это функция уровня библиотеки и, следовательно, может быть вызвана для любого объекта, который может быть успешно проанализирован.

Например, ravel будет работать со списком ndarrays, а flatten недоступен для этого типа объекта.

@IanH также указывает на важные различия в обработке памяти в своем ответе.

person Bryan P    schedule 26.11.2016
comment
спасибо за информацию о ravel (), работающем со списками ndarray - person WestCoastProjects; 28.10.2018
comment
Не только списки массивов, но и списки списков :) - person timtody; 18.06.2020

Вот правильное пространство имен для функций:

Обе функции возвращают плоские одномерные массивы, указывающие на новые структуры памяти.

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 вернет копию
  • Равель вернет взгляд.

Как мы проверяем, является ли что-то копией? Используя атрибут .base файла ndarray. Если это представление, базой будет исходный массив; если это копия, то база будет None.


Проверьте, является ли a2 копией a1

import numpy
a1 = numpy.array([[1,2],[3,4]])
a2 = a1.copy()
id(a2.base), id(a1.base)

Из:

(140735713795296, 140735713795296)
person prosti    schedule 22.01.2019
comment
id(a1.base) должен быть таким же, как id(a2.base) - person prosti; 29.01.2021