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

mrzz3bfm  于 2023-03-30  发布在  其他
关注(0)|答案(3)|浏览(117)

在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]])
c8ib6hqw

c8ib6hqw1#

如果你的数组是多维的,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提供的方法。

zf9nrax1

zf9nrax12#

这里有另一种方法:

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它们。这产生了每列索引的随机排列。
请注意,这具有次优的渐近时间复杂度,因为对于大小为m x n的数组,排序需要时间O(n m log m)。但是由于Python的for循环非常慢,因此除了非常高的矩阵之外,您实际上可以获得更好的性能。

xmq68pz9

xmq68pz93#

要沿着数组的行轴执行排列,可以使用以下代码:

np.random.permutation(arr) # If you want to make a copy of the array

或者:

np.random.shuffle(arr) # if you want to change the array in-place

但是,如果您有一个多维数组,则可以使用以下代码沿着特定轴执行置换:

sampler = np.random.permutation(4) # Size of the selected axis
df.take(sampler, axis=0) # You can select your desired axis from here
例如,假设您要沿着第二个轴排列以下数组:
在轴1上排列
arr = np.arange(20).reshape((4, 5))
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
采样器定义如下:
sampler = np.random.permutation(5)
array([2, 1, 3, 4, 0])
然后,您可以使用take()方法应用置换:
arr.take(sampler, axis = 1)

Out:
array([[ 1,  2,  3,  0,  4],
       [ 6,  7,  8,  5,  9],
       [11, 12, 13, 10, 14],
       [16, 17, 18, 15, 19]])
如果你想把所有元素沿着所有的轴排列,你可以这样做
np.random.permutation(arr.flatten()).reshape((4, 5)) # This makes a copy of the array

相关问题