在numpy中置换每列内容的最佳方法

时间:2014-12-15 14:51:00

标签: python arrays numpy shuffle

在numpy数组中有效置换每列内容的最佳方法是什么?

我所拥有的是:

>>> arr = np.arange(16).reshape((4, 4))
>>> arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

>> # Shuffle each column independently to obtain something like
array([[  8,  5, 10,  7],
       [ 12,  1,  6,  3],
       [  4,  9, 14, 11],
       [  0, 13,  2, 15]])

2 个答案:

答案 0 :(得分:7)

如果您的数组是多维的,默认情况下np.random.permutation沿第一轴(列)排列:

>>> np.random.permutation(arr)
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [12, 13, 14, 15]])

然而,这会使行索引混洗,因此每列具有相同的(随机)排序。

独立地对每列进行混洗的最简单方法是循环遍历列并使用np.random.shuffle对每个列进行混洗:

for i in range(arr.shape[1]):
    np.random.shuffle(arr[:,i])

例如:

array([[12,  1, 14, 11],
       [ 4,  9, 10,  7],
       [ 8,  5,  6, 15],
       [ 0, 13,  2,  3]])

如果您有一个非常大的数组而不想复制,则此方法非常有用,因为每个列的排列都是在适当的位置完成的。另一方面,即使是简单的Python循环也可能非常慢,并且有更快的NumPy方法,例如@jme提供的方法。

答案 1 :(得分:5)

这是另一种方法:

def permute_columns(x):
    ix_i = np.random.sample(x.shape).argsort(axis=0)
    ix_j = np.tile(np.arange(x.shape[1]), (x.shape[0], 1))
    return x[ix_i, ix_j]

快速测试:

>>> x = np.arange(16).reshape(4,4)
>>> permute_columns(x)
array([[ 8,  9,  2,  3],
       [ 0,  5, 10, 11],
       [ 4, 13, 14,  7],
       [12,  1,  6, 15]])

这个想法是生成一堆随机数,然后在每列中独立地argsort。这会产生每列索引的随机排列。

请注意,这具有次优的渐近时间复杂度,因为对于大小为O(n m log m)的数组,排序需要时间m x n。但是由于Python的for循环非常慢,所以除了非常高的矩阵外,你实际上可以获得更好的性能。