web-dev-qa-db-fra.com

Convertir un objet de carte en tableau numpy en python 3

En Python 2 je pourrais faire ce qui suit:

import numpy as np    
f = lambda x: x**2
seq = map(f, xrange(5))
seq = np.array(seq)
print seq
# prints: [ 0  1  4  9 16]

En Python 3 cela ne fonctionne plus:

import numpy as np    
f = lambda x: x**2
seq = map(f, range(5))
seq = np.array(seq)
print(seq)
# prints: <map object at 0x10341e310>

Comment obtenir l'ancien comportement (conversion des résultats map en tableau numpy)?

Edit: Comme @jonrsharpe l'a souligné dans sa réponse, cela pourrait être corrigé si je convertissais d'abord seq en liste:

seq = np.array(list(seq))

mais je préfère éviter l'appel supplémentaire à list.

22
btel

Une autre alternative, autre que les solutions valides @jonrsharpe déjà signalées, consiste à utiliser np.fromiter :

>>> import numpy as np    
>>> f = lambda x: x**2
>>> seq = map(f, range(5))
>>> np.fromiter(seq, dtype=np.int)
array([ 0,  1,  4,  9, 16])
30
Oliver W.

Bien que vous l'appeliez seq, l'objet map dans Python 3 n'est pas pas une séquence (c'est un itérateur, voir ce qui est nouveau dans Python ). numpy.array A besoin d'une séquence pour que le len puisse être déterminé et la quantité appropriée de mémoire réservée; il ne consommera pas d'itérateur. Par exemple, l'objet range, qui le fait prend en charge la plupart des opérations de séquence, peut être transmis directement;

seq = np.array(range(5))
print(seq)
# prints: [0 1 2 3 4]

Pour restaurer le comportement précédent, comme vous le savez, vous pouvez explicitement reconvertir l'objet map en une séquence (par exemple, liste ou Tuple):

seq = np.array(list(seq))  # should probably change the name!

Cependant, comme la documentation le dit:

une solution rapide consiste à envelopper map() dans list(), par exemple list(map(...)), mais une meilleure solution consiste souvent à utiliser une compréhension de liste (en particulier lorsque le code d'origine utilise lambda)

Une autre option serait donc:

seq = [f(x) for x in range(5)]

ou juste:

seq = [x**2 for x in range(5)]

Vous pouvez également utiliser numpy dès le début:

import numpy as np    
arr = np.arange(5)
arr **= 2
print(arr)
# prints [ 0  1  4  9 16] in 2.x and 3.x
8
jonrsharpe