在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]])
答案 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
循环非常慢,所以除了非常高的矩阵外,你实际上可以获得更好的性能。