2013-03-22 99 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