不带for循环的numpy数组中的字典列表

2024-04-25 14:46:53 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一种方法可以将一个操作矢量化,这个操作需要几个numpy数组并将它们放入字典列表中?在

下面是一个简化的例子。实际场景可能涉及更多数组和更多字典键。在

import numpy as np
x = np.arange(10)
y = np.arange(10, 20)
z = np.arange(100, 110)

print [dict(x=x[ii], y=y[ii], z=z[ii]) for ii in xrange(10)]

我在xrange调用中可能有数千或数十万次迭代。创建xy和{}的所有操作都是矢量化的(我的例子不像上面这样简单)。所以,只剩下1个for循环需要处理,我预计这会导致巨大的加速。在

我尝试过在函数中使用map来创建dict和其他各种解决方法。Python for循环似乎是慢的部分(与往常一样)。我有点坚持使用字典,因为有一个预先存在的API需求。然而,没有dicts和record数组或其他东西的解决方案会很有趣,但最终我不认为这将适用于现有的API。在


Tags: 方法numpyapi列表for字典np场景
3条回答

以你的小例子来说,我很难找到比列表和字典理解结合更快的东西

In [105]: timeit [{'x':i, 'y':j, 'z':k} for i,j,k in zip(x,y,z)]
100000 loops, best of 3: 15.5 µs per loop
In [106]: timeit [{'key':{'x':i, 'y':j, 'z':k}} for i,j,k in zip(x,y,z)]
10000 loops, best of 3: 37.3 µs per loop

在分区之前使用数组连接来连接数组的替代方法速度较慢。在

^{pr2}$

======================

结构化数组使用recfunctions最简单:

In [109]: from numpy.lib import recfunctions
In [112]: M=recfunctions.merge_arrays((x,y,z))
In [113]: M.dtype.names=['x','y','z']
In [114]: M
Out[114]: 
array([(0, 10, 100), (1, 11, 101), (2, 12, 102), (3, 13, 103),
       (4, 14, 104), (5, 15, 105), (6, 16, 106), (7, 17, 107),
       (8, 18, 108), (9, 19, 109)], 
      dtype=[('x', '<i4'), ('y', '<i4'), ('z', '<i4')])
In [115]: M['x']
Out[115]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

时间要慢得多,但是如果您想一次访问所有的x值,这比从所有字典中获取它们要好得多。在

np.rec.fromarrays((x,y,z),names=['x','y','z'])

生成具有给定名称的重新排列。速度差不多。在

我还可以构造一个具有正确数据类型和形状的空数组,并将数组复制到其中。这可能和这个一样快,但是描述起来更复杂。在

我建议优化数据结构以使用/访问,而不是构建速度。一般来说,一次构造,多次使用。在

==========

In [125]: dt=np.dtype([('x',x.dtype),('y',y.dtype),('z',z.dtype)])
In [126]: xyz=np.zeros(x.shape,dtype=dt)
In [127]: xyz['x']=x; xyz['y']=y; xyz['z']=z
# or for n,d in zip(xyz.dtype.names, (x,y,z)): xyz[n] = d
In [128]: xyz
Out[128]: 
array([(0, 10, 100), (1, 11, 101), (2, 12, 102), (3, 13, 103),
       (4, 14, 104), (5, 15, 105), (6, 16, 106), (7, 17, 107),
       (8, 18, 108), (9, 19, 109)], 
      dtype=[('x', '<i4'), ('y', '<i4'), ('z', '<i4')])

这是一个(Num)?Python道:

In [18]: names = np.array(['x', 'y', 'z'])
In [38]: map(dict, np.dstack((np.repeat(names[None, :], 10, axis=0), np.column_stack((x, y, z)))))
Out[38]: 
[{'x': '0', 'y': '10', 'z': '100'},
 {'x': '1', 'y': '11', 'z': '101'},
 {'x': '2', 'y': '12', 'z': '102'},
 {'x': '3', 'y': '13', 'z': '103'},
 {'x': '4', 'y': '14', 'z': '104'},
 {'x': '5', 'y': '15', 'z': '105'},
 {'x': '6', 'y': '16', 'z': '106'},
 {'x': '7', 'y': '17', 'z': '107'},
 {'x': '8', 'y': '18', 'z': '108'},
 {'x': '9', 'y': '19', 'z': '109'}]

另外,请注意,如果您不需要同时使用所有的字典,您可以简单地创建一个生成器并按需访问每个条目。在

^{pr2}$

如果您需要嵌套字典,我建议您使用列表理解:

In [88]: inner = np.dstack((np.repeat(names[None, :], 10, axis=0), np.column_stack((x, y))))

In [89]: [{'connection': d} for d in map(dict, inner)]
Out[89]: 
[{'connection': {'x': '0', 'y': '10'}},
 {'connection': {'x': '1', 'y': '11'}},
 {'connection': {'x': '2', 'y': '12'}},
 {'connection': {'x': '3', 'y': '13'}},
 {'connection': {'x': '4', 'y': '14'}},
 {'connection': {'x': '5', 'y': '15'}},
 {'connection': {'x': '6', 'y': '16'}},
 {'connection': {'x': '7', 'y': '17'}},
 {'connection': {'x': '8', 'y': '18'}},
 {'connection': {'x': '9', 'y': '19'}}]

下面是一种混合使用NumPyPandas-

# Stack into columns & create a pandas dataframe with appropriate col names
a = np.column_stack((x.ravel(),y.ravel(),z.ravel()))
df = pd.DataFrame(a,columns=[['x','y','z']])

# Convert to list of dicts
out = df.T.to_dict().values()

样本运行-

^{pr2}$

相关问题 更多 >