Qual'è la differenza tra flatten e ravel in 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]

Entrambe le funzioni restituiscono lo stesso elenco. Quindi qual è la necessità di due diverse funzioni che svolgono lo stesso lavoro.


14
Ravel di solito restituisce una vista nell'array esistente (a volte restituisce una copia). Flatten restituisce un nuovo array.
Alex


1
Ecco una dimostrazione pratica della sottile differenza.
prosti

Quindi qualcuno può fare un esempio quando è meglio appiattire un array e quando ravviarlo?
Aleksandar,

Risposte:


371

L'API corrente è che:

  • flatten restituisce sempre una copia.
  • ravelrestituisce una vista dell'array originale quando possibile. Ciò non è visibile nell'output stampato, ma se si modifica l'array restituito da ravel, è possibile che vengano modificate le voci dell'array originale. Se si modificano le voci in un array restituito da flat, ciò non accadrà mai. ravel sarà spesso più veloce poiché non viene copiata alcuna memoria, ma è necessario prestare maggiore attenzione alla modifica dell'array che restituisce.
  • reshape((-1,)) ottiene una vista ogni volta che i passi dell'array lo consentono anche se ciò significa che non si ottiene sempre un array contiguo.

30
Qualche idea sul perché gli sviluppatori NumPy non si siano attenuti a una funzione con alcuni parametri copy = [True, False]?
Franck Dernoncourt,

41
Le garanzie di backcompat a volte fanno accadere cose strane come questa. Ad esempio: gli sviluppatori intorpiditi di recente (in 1.10) hanno aggiunto una garanzia precedentemente implicita che ravel avrebbe restituito un array contiguo (una proprietà che è molto importante quando si scrivono estensioni C), quindi ora l'API deve a.flatten()procurarsene una copia, a.ravel()per evitare la maggior parte delle copie garantisce comunque che l'array restituito sia contiguo e a.reshape((-1,))di ottenere davvero una vista ogni volta che i passi dell'array lo consentono anche se ciò significa che non si ottiene sempre un array contiguo.
IanH,

4
@Hossein IanH lo ha spiegato: ravelgarantisce un array contiguo, e quindi non è garantito che restituisca una vista; reshaperestituisce sempre una vista e quindi non è garantito che restituisca un array contiguo.
Iled,

4
@Hossein Sarebbe una domanda completamente nuova. Molto brevemente, è molto più veloce leggere e scrivere in uno spazio di memoria contiguo. Ci sono diverse domande e risposte su questo qui su SO ( bell'esempio qui ), sentiti libero di aprirne uno nuovo se hai ulteriori domande.
Iled

2
reshape(-1)è equivalente areshape((-1,))
Tom Pohl il

53

Come spiegato qui una differenza chiave è che:

  • flatten è un metodo di un oggetto ndarray e quindi può essere chiamato solo per array intorpiditi veri.

  • ravel è una funzione a livello di libreria e quindi può essere chiamata su qualsiasi oggetto che può essere analizzato correttamente.

Ad esempio ravelfunzionerà su un elenco di ndarrays, mentre flattennon è disponibile per quel tipo di oggetto.

@IanH sottolinea anche importanti differenze con la gestione della memoria nella sua risposta.


4
grazie per le informazioni sul ravel () che lavora su liste di ndarray's
javadba,

Non solo elenchi di array ma anche elenchi di elenchi :)
timtody

15

Ecco lo spazio dei nomi corretto per le funzioni:

Entrambe le funzioni restituiscono array 1D appiattiti che puntano alle nuove strutture di memoria.

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

Nell'esempio superiore:

  • le posizioni di memoria dei risultati sono diverse,
  • i risultati sembrano uguali
  • appiattirebbe restituire una copia
  • il corvo avrebbe restituito una vista.

Come controlliamo se qualcosa è una copia? Utilizzando l' .baseattributo di ndarray. Se è una vista, la base sarà l'array originale; se è una copia, sarà la base None.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.