Jaka jest różnica między funkcjami spłaszczania i ravela w 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]

Obie funkcje zwracają tę samą listę. Więc jaka jest potrzeba dwóch różnych funkcji wykonujących tę samą pracę.

kryptomancja
źródło
14
Ravel zwykle zwraca widok do istniejącej tablicy (czasami zwraca kopię). Spłaszcz zwraca nową tablicę.
Alex
1
Oto praktyczny pokaz subtelnej różnicy.
prosti
Czy ktoś może podać przykład, kiedy lepiej spłaszczyć tablicę, a kiedy ją zepsuć?
Aleksandar

Odpowiedzi:

371

Obecny interfejs API jest taki, że:

  • flatten zawsze zwraca kopię.
  • ravelzwraca widok oryginalnej tablicy, gdy tylko jest to możliwe. Nie jest to widoczne na wydruku, ale jeśli zmodyfikujesz tablicę zwróconą przez ravel, może zmodyfikować wpisy w oryginalnej tablicy. Jeśli zmodyfikujesz wpisy w tablicy zwróconej z spłaszczenia, nigdy tak się nie stanie. ravel często będzie szybszy, ponieważ żadna pamięć nie jest kopiowana, ale musisz być bardziej ostrożny przy modyfikowaniu tablicy, którą zwraca.
  • reshape((-1,)) dostaje widok, ilekroć pozwalają na to kroki tablicy, nawet jeśli oznacza to, że nie zawsze otrzymujesz ciągłą tablicę.
IanH
źródło
30
Masz pojęcie, dlaczego programiści NumPy nie trzymali się jednej funkcji z jakimś parametrem copy = [True, False]?
Franck Dernoncourt
41
Gwarancje backcompat czasami powodują dziwne rzeczy. Na przykład: programiści numpy niedawno (w 1.10) dodali wcześniej niejawną gwarancję, że ravel zwróci ciągłą tablicę (właściwość, która jest bardzo ważna podczas pisania rozszerzeń C), więc teraz API ma a.flatten()na pewno pobrać kopię, a.ravel()aby uniknąć większość kopii, ale nadal gwarantuje, że zwrócona tablica jest ciągła, i a.reshape((-1,))aby naprawdę uzyskać widok za każdym razem, gdy pozwalają na to kroki, nawet jeśli oznacza to, że nie zawsze otrzymujesz ciągłą tablicę.
IanH
4
@Hossein IanH wyjaśnił to: ravelgwarantuje ciągłą tablicę, więc nie ma gwarancji, że zwróci widok; reshapezawsze zwraca widok, więc nie ma gwarancji, że zwróci ciągłą tablicę.
iled
4
@Hossein To byłoby zupełnie nowe pytanie. Krótko mówiąc, znacznie szybciej jest czytać i pisać w ciągłej przestrzeni pamięci. Istnieje kilka pytań i odpowiedzi na ten temat tutaj na SO ( fajny przykład tutaj ), zachęcamy do otwarcia nowego, jeśli masz dodatkowe pytania.
iled
2
reshape(-1)jest odpowiednikiemreshape((-1,))
Tom Pohl
53

Jak wyjaśniono tutaj, kluczową różnicą jest to, że:

  • flatten jest metodą obiektu ndarray i dlatego można ją wywoływać tylko dla prawdziwych tablic numpy.

  • ravel jest funkcją na poziomie biblioteki i dlatego można ją wywoływać w każdym obiekcie, który można pomyślnie przeanalizować.

Na przykład raveldziała na liście ndarrays, podczas gdy flattennie jest dostępna dla tego typu obiektu.

@IanH wskazuje również w swojej odpowiedzi na ważne różnice w obsłudze pamięci.

Bryan P.
źródło
4
thx za tym informacje o Ravela () działa na listach ndarray„s
javadba
Nie tylko listy tablic, ale także listy list :)
timtody
15

Oto poprawna przestrzeń nazw dla funkcji:

Obie funkcje zwracają spłaszczone tablice 1D wskazujące na nowe struktury pamięci.

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

W górnym przykładzie:

  • miejsca w pamięci wyników są różne,
  • wyniki wyglądają tak samo
  • spłaszczone zwróci kopię
  • Ravel zwróci widok.

Jak sprawdzamy, czy coś jest kopią? Korzystanie z .baseatrybutu ndarray. Jeśli jest to widok, bazą będzie oryginalna tablica; jeśli jest to kopia, bazą będzie None.

prosti
źródło