2013-03-22 100 views
24

我有一个字典,我需要转换为NumPy结构化数组。我使用的是arcpy函数NumPyArraytoTable,所以NumPy结构化数组是唯一可以工作的数据格式。python字典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) 

回答

44

你可以使用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)被认为是那些原子元素之一,它应该是一个元组,而不是一个列表。

+0

我提到这个答案你的使事情发生,它是行不通的。花了几天的时间。你能帮忙吗? http://stackoverflow.com/questions/32723802/scipy-and-preserving-mat-file-mat-matlab-data-file-structure – Raaj 2015-09-22 19:23:58

+0

直接复制和粘贴代码示例给出错误。我通过将'result.items()'更改为'list(result.items())'来修复它。 Python 3.5 – Atlas7 2017-09-22 00:36:54

+1

@ Atlas7:感谢您的提醒。答案已经更新为Python3。 – unutbu 2017-09-22 00:56:09

2

让我提出改进的方法,当dictionnary的值列表具有相同长度:

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

我宁愿存储在单独的数组键和值。这我经常更实际。阵列结构是结构阵列的完美替代品。由于大多数情况下你只需要处理一部分数据(在这种情况下是键或值,所以仅使用两个阵列中的一个阵列的操作将比两个阵列中的一半操作更有效)。但如果这种方式是不可能的,我会建议使用由列而不是按行排序的数组。通过这种方式,你将有相同的利益为具有两个数组,但只在一个包装。

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)} 
2

E VEN更简单,如果你接受使用熊猫:

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