Nouveau sur Python. Je travaillais avec numpy quand je suis tombé sur nditer () qui itère sur des tableaux multidimensionnels pour nous donner un scalaire. Je ne sais pas trop comment cela fonctionne ou se comporte.
arr2 = np.array([[1, 2, 3],[4, 5, 6, 7]])
for x in np.nditer(arr2):
print(x,end=" ")
Il donne 1 2 3 4 5 6
Cependant, si je change le no des éléments dans l'un des tableaux, cela génère une erreur.
arr2 = np.array([[1, 2, 3],[4, 5, 6]])
for x in np.nditer(arr2):
print(x,end=" ")
TypeError : l'opérande d'itérateur ou le dtype demandé contient des références, mais l'indicateur REFS_OK n'était pas activé
Qu'est-ce que je fais mal, ou nditer () ne fonctionne qu'avec des tableaux de forme régulière? Est-il possible d'obtenir des valeurs scalaires à partir d'un ndarray de forme irrégulière (sans utiliser la boucle for bien sûr)?
3 Réponses :
Vous pouvez aplatir le ndarray en utilisant:
arr2.sum() # Result will be: [1, 2, 3, 4, 5, 6, 7]
Ensuite, vous pouvez continuer à obtenir les valeurs scalaires dans une seule boucle for.
Explication plus détaillée ici .
la différence est que lorsque vous déclarez arr2 = np.array([[1, 2, 3],[4, 5, 6, 7]]) le résultat n'est pas une donnée structurée et elle sera affectée comme un tableau de type objet contenant une liste de listes:
import numpy as np
arr2 = np.concatenate([[1, 2, 3],[4, 5, 6, 7]])
for x in np.nditer(arr2):
print(x,end=" ")
et lorsque vous entrez une donnée structurée, la sortie sera un tableau avec le type de vos entrées (int64, float64, etc.) et avec une dimension correspondante.
Si vous avez un groupe de listes de tailles différentes, la meilleure solution est de créer une liste contenant tous les éléments et de les parcourir. Et si vous voulez vous en tenir à numpy, vous pouvez faire np.concatenate([[1,2,3],[4,5,6,7]]) qui renverra un tableau aplatir de dimension 1 sur lequel vous pourrez également itérer .
array([list([1, 2, 3]), list([4,5,6,7])], dtype=object)
Le premier cas produit un tableau numérique 2D:
In [16]: for x in np.nditer(arr2, flags=['refs_ok']):
...: print(x, x.shape, type(x))
[1, 2, 3] () <class 'numpy.ndarray'>
[4, 5, 6, 7] () <class 'numpy.ndarray'>
Vous pouvez facilement remodeler un tel tableau:
In [13]: for x in np.nditer(arr):
...: print(x, x.shape, type(x))
...:
1 () <class 'numpy.ndarray'>
2 () <class 'numpy.ndarray'>
3 () <class 'numpy.ndarray'>
4 () <class 'numpy.ndarray'>
5 () <class 'numpy.ndarray'>
6 () <class 'numpy.ndarray'>
Les opérations de tableau entier comme celle-ci sont de loin préférées aux boucles ou à une autre itération (cachée) (en code Python).
Le second cas ne produit pas de tableau 2d:
In [10]: alist = [[1,2,3],[4,5,6,7]] In [12]: [i for j in alist for i in j] Out[12]: [1, 2, 3, 4, 5, 6, 7]
C'est un tableau à 2 éléments contenant des listes. C'est similaire à la liste source des listes.
ravel ne fonctionnera pas car il est déjà 1d. Cependant, nous pouvons concaténer les listes en un seul tableau:
In [9]: np.hstack(arr2) Out[9]: array([1, 2, 3, 4, 5, 6, 7])
Nous n'avons pas besoin d'utiliser numpy avec une telle liste de listes.
In [5]: arr2 = np.array([[1,2,3],[4,5,6,7]]) <ipython-input-5-4a78eda0f1a8>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray arr2 = np.array([[1,2,3],[4,5,6,7]]) In [6]: arr2 = np.array([[1,2,3],[4,5,6,7]], object) In [7]: arr2 Out[7]: array([list([1, 2, 3]), list([4, 5, 6, 7])], dtype=object) In [8]: arr2.shape Out[8]: (2,)
===
np.nditer besoin de clauses de non-responsabilité plus np.nditer . Il est préférable de le considérer comme un pont vers l'écriture de code compilé (avec cython ), et non comme un outil principal dans le code Python. Il n'améliore pas la vitesse et n'évite pas les «boucles». Il y a beaucoup de cloches et de sifflets qui peuvent être utiles, mais qui ne font que confondre les débutants.
In [4]: arr.ravel() Out[4]: array([1, 2, 3, 4, 5, 6])
Tel que vous l'avez utilisé, x est un tableau numpy avec shape () (0d). Parfois, c'est utile, mais cela ne fera probablement que confondre un débutant.
En travaillant à partir de votre message d'erreur et des documents, je peux itérer sur arr2 :
In [1]: arr = np.array([[1,2,3],[4,5,6]])
In [2]: arr
Out[2]:
array([[1, 2, 3],
[4, 5, 6]])
In [3]: arr.shape
Out[3]: (2, 3)
Comme avant x est un tableau 0d, seulement dans ce cas, l'élément de ce tableau est un objet, une liste. Cela n'aide donc pas si votre objectif est une itération aplatie.
Ne vous embêtez pas avec
nditer. Ce n'est généralement pas nécessaire et déroutant pour les débutants. Essayez d'éviter les itérations sur les tableaux.