我有一本字典,我需要转换为NumPy的结构数组。 我使用的ArcPy中功能NumPyArraytoTable
,所以NumPy的结构数组,将工作的唯一数据格式。
在此基础上螺纹: 写从字典numpy的阵列和这个线程: 如何Python字典对象转换为numpy的阵列
我已经试过这样:
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)
你可以使用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
对待名单不同于元组: 罗伯特·科恩解释说 :
作为一项规则,元组被认为是“标量”记录和名单在递归。 此规则有助于numpy.array()找出哪些序列是记录的,哪些是在将被递归其它序列; 即,其序列创建另一个尺寸和它们的原子元素。
由于(0.0, 1.1181753789488595)
被认为是那些原子元素之一,它应该是一个元组,而不是一个列表。
更简单,如果你接受使用熊猫:
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
让我提出改进的方法,当dictionnary的值具有相同lenght列表:
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
我宁愿存储在单独的数组键和值。 这个我经常更为实际。 阵列的结构是完美的替代,以结构的阵列。 正如你们大多数人都只能处理您的数据子集的时间(在这种情况下键或值,只能用仅有的两个数组的一个操作会比用两个数组的一半一起操作更有效率。
但如果这种方式是不可能的,我会建议使用由列而不是按行排序的阵列。 通过这种方式,你将有相同的利益为具有两个数组,但只在一个包装。
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)}