web-dev-qa-db-fra.com

tableau structuré de python à numpy

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)
31
Christa

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.

49
unutbu

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
3
dgdm

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
2
dgdm

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)}
1
Federico Ressi