给出以下NumPy数组,
> a = array([[1, 2, 3, 4, 5], [1, 2, 3, 4, 5],[1, 2, 3, 4, 5]])
简单到足以改变一行,
> shuffle(a[0])
> a
array([[4, 2, 1, 3, 5],[1, 2, 3, 4, 5],[1, 2, 3, 4, 5]])
是否可以使用索引表示法独立地对每个行进行洗牌?或者你必须迭代数组。我记得像,
> numpy.shuffle(a[:])
> a
array([[4, 2, 3, 5, 1],[3, 1, 4, 5, 2],[4, 2, 1, 3, 5]]) # Not the real output
虽然这显然不起作用。
答案 0 :(得分:18)
你必须多次调用numpy.random.shuffle()
因为你正在独立地改变几个序列。 numpy.random.shuffle()
适用于任何可变序列,实际上不是ufunc
。分别对二维数组a
的所有行进行混洗的最短和最有效的代码可能是
map(numpy.random.shuffle, a)
答案 1 :(得分:1)
rand+argsort
技巧的矢量化解决方案我们可以沿着指定的轴生成唯一索引,并使用advanced-indexing
索引到输入数组中。为了生成唯一索引,我们将使用random float generation + sort
trick,从而为我们提供矢量化解决方案。我们还将泛化它以覆盖通用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)
请注意,这种混洗不会就地进行,并且会返回经过混洗的副本。
样品运行-
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]])