从字典列表中创建NumPy记录数组的最简单方法?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从字典列表中创建NumPy记录数组的最简单方法?相关的知识,希望对你有一定的参考价值。
说我有d = [dict(animal='cat', weight=5), dict(animal='dog', weight=20)]
之类的数据(基本上是JSON,其中所有条目都具有一致的数据类型)。
在Pandas中,您可以使用df = pandas.DataFrame(d)
将此表制成表–是否有可与普通NumPy记录数组媲美的东西? np.rec.fromrecords(d)
似乎没有给我想要的东西。
您可以创建一个具有正确大小和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')]
好吧,因为numpy不使用列标题,所以您可以使生活更加轻松,并且仅依赖于Pandas
Pandas
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])
我的建议(通常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)
以上是关于从字典列表中创建NumPy记录数组的最简单方法?的主要内容,如果未能解决你的问题,请参考以下文章
使用 C# 在 ASP.NET MVC 3 中创建级联下拉列表的最简单方法