我有一个字典,我需要转换为NumPy结构化数组。我正在使用arcpy函数NumPyArraytoTable
,因此NumPy结构化数组是唯一可用的数据格式。
基于此主题:Writing to numpy array from dictionary和此主题:How to convert Python dictionary object to numpy array
我试过这个:
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)
但我一直得到expected a readable buffer object
下面的方法有效,但是很愚蠢,显然不适用于真实数据。我知道有一种更优雅的方法,我无法理解。
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)
答案 0 :(得分:49)
您可以使用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))
产量
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')])
如果您不想创建元组的中间列表list(result.items())
,那么您可以改为使用np.fromiter
:
在Python2中:
array = np.fromiter(result.iteritems(), dtype=dtype, count=len(result))
在Python3中:
array = np.fromiter(result.items(), dtype=dtype, count=len(result))
为什么使用列表[key,val]
不起作用:
顺便说一下,你的尝试,
numpy.array([[key,val] for (key,val) in result.iteritems()],dtype)
非常接近工作。如果您将列表[key, val]
更改为元组(key, val)
,那么它就可以了。当然,
numpy.array([(key,val) for (key,val) in result.iteritems()], dtype)
与
相同numpy.array(result.items(), dtype)
在Python2中,或
numpy.array(list(result.items()), dtype)
在Python3中。
np.array
处理列表的方式与元组不同:Robert Kern explains:
通常,元组被视为“标量”记录,列表是 递归。这个规则有助于numpy.array()找出哪个 序列是记录,是要递归的其他序列 根据;即哪些序列创建另一个维度,哪个序列是 原子元素。
由于(0.0, 1.1181753789488595)
被认为是那些原子元素之一,它应该是一个元组,而不是一个列表。
答案 1 :(得分:3)
如果你接受使用熊猫,那就更简单了:
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
给出:
0 1 2 3 4 5 6
0 1.118175 0.556608 0.471827 0.487167 1 0.139508 0.209416
答案 2 :(得分:2)
当字典的值是具有相同长度的列表时,让我提出一种改进的方法:
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
答案 3 :(得分:1)
我更希望在单独的数组上存储键和值。这我常常更实际。阵列结构是结构阵列的完美替代品。由于大多数情况下您只需要处理数据的一部分(在这种情况下只需要键或值,因此仅使用两个数组中的一个进行操作比使用两个数组中的一半进行操作更有效。
但是如果这种方式不可行,我建议使用按列而不是按行排序的数组。通过这种方式,您可以获得与拥有两个数组相同的好处,但只能打包一个。
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()
但我最喜欢的是这个(更简单):
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)}
答案 4 :(得分:0)
类似于批准的答案。如果要通过字典键创建数组:
np.array( tuple(dict.keys()) )
如果要根据字典值创建数组:
np.array( tuple(dict.values()) )