web-dev-qa-db-fra.com

Quelle est la différence entre les fonctions flatten et ravel dans 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]

Les deux fonctions renvoient la même liste. Alors quel est le besoin de deux fonctions différentes effectuant le même travail.

244
DEEPAK YADAV

L'API actuelle est la suivante:

  • flatten renvoie toujours une copie.
  • ravel renvoie une vue du tableau d'origine chaque fois que possible. Cela n'est pas visible dans la sortie imprimée, mais si vous modifiez le tableau renvoyé par ravel, cela peut modifier les entrées du tableau d'origine. Si vous modifiez les entrées d'un tableau retourné d'aplatissement, cela n'arrivera jamais. ravel sera souvent plus rapide car aucune mémoire n'est copiée, mais vous devez être plus prudent lorsque vous modifiez le tableau qu'il renvoie.
  • reshape((-1,)) obtient une vue chaque fois que les sauts du tableau le permettent, même si cela signifie que vous n'obtenez pas toujours un tableau contigu.
322
IanH

Comme expliqué ici une différence clé est que flatten est une méthode d'un objet ndarray et ne peut donc être appelée que pour de véritables tableaux numpy. En revanche, ravel() est une fonction au niveau de la bibliothèque et peut donc être appelée sur tout objet pouvant être analysé avec succès. Par exemple, ravel() fonctionnera sur une liste de ndarrays, tandis que flatten n'est pas disponible pour ce type d'objet.

@IanH souligne également des différences importantes avec la gestion de la mémoire dans sa réponse.

35
Bryan P

Voici l'espace de noms correct pour les fonctions:

Les deux fonctions renvoient des tableaux 1D aplatis pointant vers les nouvelles structures de mémoire.

_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
_

Dans l'exemple supérieur:

  • les emplacements mémoire des résultats sont différents,
  • les résultats se ressemblent
  • aplatir renverrait une copie
  • ravel retournerait une vue.

Comment vérifier si quelque chose est une copie? Utilisation de l'attribut _.base_ de ndarray. Si c'est une vue, la base sera le tableau d'origine; si c'est une copie, la base sera None.

10
prosti