如何将这个嵌套循环转换为numpy广播



我想重新排列我的数据(两个偶数长度的1d数组(:

cs = [w x y z]
rs = [a b c d e f]

得出这样的结果:

[[a b w x]
[c d w x]
[e f w x]
[a b y z]
[c d y z]
[e f y z]]

这是我尝试过的(有效(:

ls = []
for c in range(0,len(cs),2):
for r in range(0,len(rs),2):
item = [rs[r], rs[r+1], cs[c], cs[c+1]]
ls.append(item)

但我希望使用整形/广播或其他numpy函数来获得相同的结果。在numpy中完成此任务的惯用方法是什么?

您可以平铺rs的元素,重复cs的元素,然后将它们排列为2D阵列的列:

import numpy as np
cs = np.array(['w', 'x', 'y', 'z'])
rs = np.array(['a', 'b', 'c', 'd', 'e', 'f'])
res = np.c_[np.tile(rs[::2], len(cs) // 2), np.tile(rs[1::2], len(cs) // 2),
np.repeat(cs[::2], len(rs) // 2), np.repeat(cs[1::2], len(rs) // 2)]

结果:

array([['a', 'b', 'w', 'x'],
['c', 'd', 'w', 'x'],
['e', 'f', 'w', 'x'],
['a', 'b', 'y', 'z'],
['c', 'd', 'y', 'z'],
['e', 'f', 'y', 'z']], dtype='<U1')

另一种选择:

np.c_[np.tile(rs.reshape(-1, 2), (len(cs) // 2, 1)),
np.repeat(cs.reshape(-1, 2), len(rs) // 2, axis=0)]

使用tile/repeat的替代方法是生成重复的行索引。

使两个阵列重新成形,因为它们将被组合:

In [106]: rs=np.reshape(list('abcdef'),(3,2))
In [107]: cs=np.reshape(list('wxyz'),(2,2))
In [108]: rs
Out[108]: 
array([['a', 'b'],
['c', 'd'],
['e', 'f']], dtype='<U1')
In [109]: cs
Out[109]: 
array([['w', 'x'],
['y', 'z']], dtype='<U1')

制作类似"网格"的索引(也可以使用itertools.product(

In [110]: IJ = np.indices((3,2))
In [111]: IJ
Out[111]: 
array([[[0, 0],
[1, 1],
[2, 2]],
[[0, 1],
[0, 1],
[0, 1]]])

reshapeorder给出了两个1d阵列:

In [112]: I,J=IJ.reshape(2,6,order='F')
In [113]: I,J
Out[113]: (array([0, 1, 2, 0, 1, 2]), array([0, 0, 0, 1, 1, 1]))

然后只需对rscs进行索引,并将它们与hstack:组合

In [114]: np.hstack((rs[I],cs[J]))
Out[114]: 
array([['a', 'b', 'w', 'x'],
['c', 'd', 'w', 'x'],
['e', 'f', 'w', 'x'],
['a', 'b', 'y', 'z'],
['c', 'd', 'y', 'z'],
['e', 'f', 'y', 'z']], dtype='<U1')

编辑

这是另一种看起来更高级的方式。使用sliding_window_view;块";Out[114]结果的视图:

In [130]: np.lib.stride_tricks.sliding_window_view(_114,(3,2))[::3,::2,:,:]
Out[130]: 
array([[[['a', 'b'],
['c', 'd'],
['e', 'f']],
[['w', 'x'],
['w', 'x'],
['w', 'x']]],

[[['a', 'b'],
['c', 'd'],
['e', 'f']],
[['y', 'z'],
['y', 'z'],
['y', 'z']]]], dtype='<U1')

有了更多的逆向工程,我发现我可以用创建Out[114]

In [147]: res = np.zeros((6,4),'U1')
In [148]: res1 = np.lib.stride_tricks.sliding_window_view(res,(3,2),writeable=True)[::3,::2,:,:]
In [149]: res1[:,0,:,:] = rs
In [150]: res1[:,1,:,:] = cs[:,None,:]
In [151]: res
Out[151]: 
array([['a', 'b', 'w', 'x'],
['c', 'd', 'w', 'x'],
['e', 'f', 'w', 'x'],
['a', 'b', 'y', 'z'],
['c', 'd', 'y', 'z'],
['e', 'f', 'y', 'z']], dtype='<U1')

我不能说这两种都是优越的,但它们表明有各种各样的方式;矢量化";这种阵列布局。

最新更新