J'ai un dictionnaire que je dois convertir en tableau structuré NumPy. J'utilise la fonction arcpy NumPyArraytoTable
, de sorte qu'un tableau structuré NumPy est le seul format de données qui fonctionnera.
Basé sur ce fil: Écriture dans un tableau numpy à partir du dictionnaire et de ce fil: Comment convertir un objet du dictionnaire Python en tableau numpy
J'ai essayé ceci:
result = {0: 1.1181753789488595, 1: 0.5566080288678394, 2: 0.4718269778030734, 3: 0.48716683119447185, 4: 1.0, 5: 0.1395076201641266, 6: 0.20941558441558442}
names = ['id','data']
formats = ['f8','f8']
dtype = dict(names = names, formats=formats)
array=numpy.array([[key,val] for (key,val) in result.iteritems()],dtype)
Mais je continue à obtenir expected a readable buffer object
La méthode ci-dessous fonctionne, mais est stupide et ne fonctionnera évidemment pas pour les données réelles. Je sais qu'il existe une approche plus gracieuse, je ne peux tout simplement pas le comprendre.
totable = numpy.array([[key,val] for (key,val) in result.iteritems()])
array=numpy.array([(totable[0,0],totable[0,1]),(totable[1,0],totable[1,1])],dtype)
Vous pouvez utiliser np.array(list(result.items()), dtype=dtype)
:
import numpy as np
result = {0: 1.1181753789488595, 1: 0.5566080288678394, 2: 0.4718269778030734, 3: 0.48716683119447185, 4: 1.0, 5: 0.1395076201641266, 6: 0.20941558441558442}
names = ['id','data']
formats = ['f8','f8']
dtype = dict(names = names, formats=formats)
array = np.array(list(result.items()), dtype=dtype)
print(repr(array))
les rendements
array([(0.0, 1.1181753789488595), (1.0, 0.5566080288678394),
(2.0, 0.4718269778030734), (3.0, 0.48716683119447185), (4.0, 1.0),
(5.0, 0.1395076201641266), (6.0, 0.20941558441558442)],
dtype=[('id', '<f8'), ('data', '<f8')])
Si vous ne voulez pas créer la liste intermédiaire de tuples, list(result.items())
, vous pouvez utiliser np.fromiter
à la place.
En Python2:
array = np.fromiter(result.iteritems(), dtype=dtype, count=len(result))
En Python3:
array = np.fromiter(result.items(), dtype=dtype, count=len(result))
Pourquoi utiliser la liste [key,val]
ne fonctionne pas:
Au fait, votre tentative,
numpy.array([[key,val] for (key,val) in result.iteritems()],dtype)
était très proche de travailler. Si vous modifiez la liste [key, val]
en tuple (key, val)
, cela aurait fonctionné. Bien sûr,
numpy.array([(key,val) for (key,val) in result.iteritems()], dtype)
est la même chose que
numpy.array(result.items(), dtype)
en Python2, ou
numpy.array(list(result.items()), dtype)
en Python3.
np.array
traite les listes différemment des tuples: Robert Kern explique :
En règle générale, les n-uplets sont considérés comme des enregistrements "scalaires" et les listes sont recursed on. Cette règle aide numpy.array () à déterminer lequel les séquences sont des enregistrements et qui sont d'autres séquences à récurrencer sur; c'est-à-dire quelles séquences créent une autre dimension et lesquelles sont les éléments atomiques.
Puisque (0.0, 1.1181753789488595)
est considéré comme l'un de ces éléments atomiques, il devrait s'agir d'un tuple et non d'une liste.
Encore plus simple si vous acceptez l'utilisation de pandas:
import pandas
result = {0: 1.1181753789488595, 1: 0.5566080288678394, 2: 0.4718269778030734, 3: 0.48716683119447185, 4: 1.0, 5: 0.1395076201641266, 6: 0.20941558441558442}
df = pandas.DataFrame(result, index=[0])
print df
donne:
0 1 2 3 4 5 6
0 1.118175 0.556608 0.471827 0.487167 1 0.139508 0.209416
Permettez-moi de proposer une méthode améliorée lorsque les valeurs du dictionnaire sont des listes de même longueur:
import numpy
def dctToNdarray (dd, szFormat = 'f8'):
'''
Convert a 'rectangular' dictionnary to numpy NdArray
entry
dd : dictionnary (same len of list
retrun
data : numpy NdArray
'''
names = dd.keys()
firstKey = dd.keys()[0]
formats = [szFormat]*len(names)
dtype = dict(names = names, formats=formats)
values = [Tuple(dd[k][0] for k in dd.keys())]
data = numpy.array(values, dtype=dtype)
for i in range(1,len(dd[firstKey])) :
values = [Tuple(dd[k][i] for k in dd.keys())]
data_tmp = numpy.array(values, dtype=dtype)
data = numpy.concatenate((data,data_tmp))
return data
dd = {'a':[1,2.05,25.48],'b':[2,1.07,9],'c':[3,3.01,6.14]}
data = dctToNdarray(dd)
print data.dtype.names
print data
Je préférerais stocker les clés et les valeurs sur des tableaux distincts. C'est souvent plus pratique. Les structures de tableaux sont un remplacement parfait pour un tableau de structures. Comme la plupart du temps, vous ne devez traiter qu'un sous-ensemble de vos données (dans ce cas, des clés ou des valeurs, opérer uniquement avec un seul des deux tableaux serait plus efficace que de fonctionner avec la moitié des deux tableaux simultanément.
Mais au cas où cela ne serait pas possible, je suggérerais d'utiliser des tableaux triés par colonne plutôt que par ligne. De cette façon, vous auriez le même avantage que d'avoir deux tableaux, mais emballés dans un seul.
import numpy as np
result = {0: 1.1181753789488595, 1: 0.5566080288678394, 2: 0.4718269778030734, 3: 0.48716683119447185, 4: 1.0, 5: 0.1395076201641266, 6: 0.20941558441558442}
names = 0
values = 1
array = np.empty(shape=(2, len(result)), dtype=float)
array[names] = r.keys()
array[values] = r.values()
Mais mon préféré est le suivant (plus simple):
import numpy as np
result = {0: 1.1181753789488595, 1: 0.5566080288678394, 2: 0.4718269778030734, 3: 0.48716683119447185, 4: 1.0, 5: 0.1395076201641266, 6: 0.20941558441558442}
arrays = {'names': np.array(k.keys(), dtype=float),
'values': np.array(k.values(), dtype=float)}