В чем разница между функциями 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]

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

Ответ 1

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

  • flatten всегда возвращает копию.
  • ravel возвращает представление исходного массива, когда это возможно. Это не видно на распечатанном выходе, но если вы измените массив, возвращаемый ravel, он может изменить записи в исходном массиве. Если вы измените записи в массиве, возвращенном из сглаживания, этого никогда не произойдет. ravel часто будет быстрее, поскольку память не копируется, но вы должны быть более осторожны в изменении массива, который он возвращает.
  • reshape((-1,)) получает представление всякий раз, когда шаги массива позволяют это, даже если это означает, что вы не всегда получаете смежный массив.

Ответ 2

Как объясняется здесь, ключевым отличием является то, что flatten является методом объекта ndarray и, следовательно, может быть вызван только для истинных массивов numpy. Напротив, ravel() является функцией уровня библиотеки и, следовательно, может быть вызвана на любой объект, который может быть успешно проанализирован. Например, ravel() будет работать над списком ndarrays, а flatten недоступен для этого типа объекта.

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

Ответ 3

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

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

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.