从字典列表中创建NumPy记录数组的最简单方法是什么?

时间:2014-07-16 23:48:35

标签: python numpy

假设我有d = [dict(animal='cat', weight=5), dict(animal='dog', weight=20)]之类的数据(基本上是JSON,其中所有条目都有一致的数据类型)。

在Pandas中你可以用df = pandas.DataFrame(d)创建一个表 - 是否有类似于普通NumPy记录数组的东西? np.rec.fromrecords(d)似乎没有给我我想要的东西。

4 个答案:

答案 0 :(得分:5)

你可以创建一个正确大小和dtype的空结构化数组,然后从列表中填充它。

http://docs.scipy.org/doc/numpy/user/basics.rec.html

  

结构化数组可以按字段或逐行填充。   ...   如果你逐行填充它,它需要一个元组(但不是列表或数组!):

In [72]: dt=dtype([('weight',int),('animal','S10')])

In [73]: values = [tuple(each.values()) for each in d]

In [74]: values
Out[74]: [(5, 'cat'), (20, 'dog')]
dt中的

字段与values中的字段顺序相同。

In [75]: a=np.zeros((2,),dtype=dt)

In [76]: a[:]=[tuple(each.values()) for each in d]

In [77]: a
Out[77]: 
array([(5, 'cat'), (20, 'dog')], 
      dtype=[('weight', '<i4'), ('animal', 'S10')])

通过更多测试,我发现我可以直接从values创建数组。

In [83]: a = np.array(values, dtype=dt)

In [84]: a
Out[84]: 
array([(5, 'cat'), (20, 'dog')], 
      dtype=[('weight', '<i4'), ('animal', 'S10')])

dtype可以从一个(或多个)字典项中推断出来:

def gettype(v):
    if isinstance(v,int): return 'int'
    elif isinstance(v,float): return 'float'
    else:
        assert isinstance(v,str)
        return '|S%s'%(len(v)+10)
d0 = d[0]
names = d0.keys()
formats = [gettype(v) for v in d0.values()]
dt = np.dtype({'names':names, 'formats':formats})
制造

dtype=[('weight', '<i4'), ('animal', 'S13')]

答案 1 :(得分:4)

好吧,你可以让你的生活更轻松,只需依靠熊猫,因为numpy不使用列标题

<强>熊猫

df = pandas.DataFrame(d)
numpyMatrix = df.as_matrix() #spits out a numpy matrix

或者您可以忽略Pandas并使用numpy + list comprehension将dicts击倒为值并存储为矩阵

<强> numpy的

numpMatrix = numpy.matrix([each.values() for each in d])

答案 2 :(得分:1)

我的建议(通常略微改进hpaulj's answer):

dicts = [dict(animal='cat', weight=5), dict(animal='dog', weight=20)]

创建od dtype对象:

dt_tuples = []
for key, value in dicts[0].items():
    if not isinstance(value, str):
        value_dtype = np.array([value]).dtype
    else:
        value_dtype = '|S{}'.format(max([len(d[key]) for d in dicts]))
    dt_tuples.append((key, value_dtype))
dt = np.dtype(dt_tuples)

如您所见,字符串处理存在问题-我们需要检查它的最大长度以定义dtype。如果您的字典中没有字符串值,或者您确定所有这些值的长度都完全相同,则可以跳过此附加条件。

如果您要寻找单线飞机,将是这样的:

dt = np.dtype([(k, np.array([v]).dtype if not isinstance(v, str) else '|S{}'.format(max([len(d[k]) for d in dicts]))) for k, v in dicts[0].items()])

(出于可读性考虑,最好将其破坏)。

值列表:

values = [tuple(d[name] for name in dt.names) for d in dicts]

因为我们遍历dt.names,所以我们确定值的顺序是正确的。

最后,创建数组:

a = np.array(values, dtype=dt)

答案 3 :(得分:-1)

您可以使用np.asaray()

In [1]: import numpy as np

In [2]: d =np.asarray( [dict(animal='cat', weight=5), dict(animal='dog', weight=20)])

In [3]: d
Out[3]: array([{'weight': 5, 'animal': 'cat'}, {'weight': 20, 'animal': 'dog'}], dtype=object)