给定置换矩阵的numpy数组的每行(或列)的有效置换

时间:2017-06-29 05:34:57

标签: python numpy multidimensional-array permutation

让我们假设,我有两个给定的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

1 个答案:

答案 0 :(得分:1)

定义“最佳”是有争议的,但这是advanced-indexing -

的一种方式
mask[:,mapping, np.arange(F)[:,None]].swapaxes(1,2)

另一种方法是转置mapping,然后将范围数组用于最后一个轴而不延伸到2Dlast axis (axis=-1)的每一行mapping决定second last axis (axis=-2) mask的元素顺序。所以,我们需要在mapping上进行转置。在第一种方法中,我们通过后者的轴交换实现了这种转置行为。我会保证效率这个。

因此,我们将实施,如此 -

mask[:,mapping.T, np.arange(F)]