让我们假设,我有两个给定的ndarray
s,其中矩阵mapping
包含如何置换矩阵mask
的行的信息。我们可以假设,mapping
矩阵来自其他算法。
import numpy as np
T, K, F = 2, 3, 5
mask = np.random.randint(4, size=(T, K, F))
mapping = np.asarray([
[0, 1, 2],
[0, 1, 2],
[2, 0, 1],
[0, 1, 2],
[1, 0, 2]
])
执行此操作的直接方法是应用for
循环:
out = np.empty_like(mask)
for f in range(F):
out[:, :, f] = mask[:, mapping[f, :], f]
这似乎非常有效,所以我查看了Numpy advanced indexing并找到了这个解决方案:
out = mask[
np.arange(T)[:, None, None],
mapping.T[None, :, :],
np.arange(F)[None, None, :]
]
相关问题的answer建议使用ogrid
:
ogrid = np.ogrid[:T, :1, :F]
out = mask[
ogrid[0],
mapping.T[None, :, :],
ogrid[2]
]
创建所有中间阵列并正确播放它们似乎非常不舒服。那么,执行所需重新排序的最佳方法是什么?
时间信息:
为了提供有意义的时间信息,我使用了一些形状,更接近我的应用程序。随机排列只是为了简洁示例。
T, K, F = 1000, 3, 257
mask = np.random.randint(4, size=(T, K, F))
mapping = np.stack([list(np.random.permutation(np.arange(3))) for _ in range(F)])
结果如下:
for loop: 100 loops, best of 3: 8.4 ms per loop
three times broadcasting: 100 loops, best of 3: 8.37 ms per loop
ogrid: 100 loops, best of 3: 8.33 ms per loop
swapaxis: 100 loops, best of 3: 2.43 ms per loop
transpose: 100 loops, best of 3: 2.08 ms per loop
答案 0 :(得分:1)
定义“最佳”是有争议的,但这是advanced-indexing
-
mask[:,mapping, np.arange(F)[:,None]].swapaxes(1,2)
另一种方法是转置mapping
,然后将范围数组用于最后一个轴而不延伸到2D
。 last axis (axis=-1)
的每一行mapping
决定second last axis (axis=-2)
mask
的元素顺序。所以,我们需要在mapping
上进行转置。在第一种方法中,我们通过后者的轴交换实现了这种转置行为。我会保证效率这个。
因此,我们将实施,如此 -
mask[:,mapping.T, np.arange(F)]