沿给定轴改组NumPy数组

laf*_*ras 16 python random numpy

给定以下NumPy数组,

> a = array([[1, 2, 3, 4, 5], [1, 2, 3, 4, 5],[1, 2, 3, 4, 5]])
Run Code Online (Sandbox Code Playgroud)

它很简单,可以改变一行,

> shuffle(a[0])
> a
array([[4, 2, 1, 3, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]])
Run Code Online (Sandbox Code Playgroud)

是否可以使用索引表示法独立地对每个行进行洗牌?或者你必须迭代数组.我有类似的想法,

> numpy.shuffle(a[:])
> a
array([[4, 2, 3, 5, 1],[3, 1, 4, 5, 2],[4, 2, 1, 3, 5]]) # Not the real output
Run Code Online (Sandbox Code Playgroud)

虽然这显然不起作用.

Sve*_*ach 19

你必须numpy.random.shuffle()多次打电话,因为你正在独立地改变几个序列. numpy.random.shuffle()适用于任何可变序列,实际上不是ufunc.分别对二维数组的所有行进行混洗的最短和最有效的代码a可能是

map(numpy.random.shuffle, a)
Run Code Online (Sandbox Code Playgroud)


use*_*991 9

对于最近关注此问题的人,numpy提供了沿指定轴独立地permuted对数组进行洗牌的方法。

来自他们的文档(使用random.Generator

rng = np.random.default_rng()
x = np.arange(24).reshape(3, 8)
x
array([[ 0,  1,  2,  3,  4,  5,  6,  7],
       [ 8,  9, 10, 11, 12, 13, 14, 15],
       [16, 17, 18, 19, 20, 21, 22, 23]])

y = rng.permuted(x, axis=1)
y
array([[ 4,  3,  6,  7,  1,  2,  5,  0],  
       [15, 10, 14,  9, 12, 11,  8, 13],
       [17, 16, 20, 21, 18, 22, 23, 19]])
Run Code Online (Sandbox Code Playgroud)


Div*_*kar 5

用量化的解决方案rand+argsort绝招

我们可以沿着指定的轴生成唯一索引,并使用索引到输入数组中advanced-indexing。为了生成唯一索引,我们将使用random float generation + sort把戏,从而为我们提供向量化解决方案。我们还将泛化它以覆盖泛型n-dim数组并与泛型axes一起使用np.take_along_axis。最终的实现看起来像这样-

def shuffle_along_axis(a, axis):
    idx = np.random.rand(*a.shape).argsort(axis=axis)
    return np.take_along_axis(a,idx,axis=axis)
Run Code Online (Sandbox Code Playgroud)

请注意,此混洗不会就位,并且会返回经过混洗的副本。

样品运行-

In [33]: a
Out[33]: 
array([[18, 95, 45, 33],
       [40, 78, 31, 52],
       [75, 49, 42, 94]])

In [34]: shuffle_along_axis(a, axis=0)
Out[34]: 
array([[75, 78, 42, 94],
       [40, 49, 45, 52],
       [18, 95, 31, 33]])

In [35]: shuffle_along_axis(a, axis=1)
Out[35]: 
array([[45, 18, 33, 95],
       [31, 78, 52, 40],
       [42, 75, 94, 49]])
Run Code Online (Sandbox Code Playgroud)