numpy随机随意洗牌

时间:2016-03-28 23:37:31

标签: numpy shuffle

我有以下数组:

 a= array([[  1,  2, 3],
           [  1,  2, 3],
           [  1,  2, 3])

我知道np.random,shuffle(a.T)将沿着行排列数组,但我需要的是依赖于每一行的shuffe。怎么能在numpy中完成?速度至关重要,因为将有数百万行。

对于此特定问题,每行将包含相同的起始填充。

5 个答案:

答案 0 :(得分:7)

import numpy as np
np.random.seed(2018)

def scramble(a, axis=-1):
    """
    Return an array with the values of `a` independently shuffled along the
    given axis
    """ 
    b = a.swapaxes(axis, -1)
    n = a.shape[axis]
    idx = np.random.choice(n, n, replace=False)
    b = b[..., idx]
    return b.swapaxes(axis, -1)

a = a = np.arange(4*9).reshape(4, 9)
# 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, 24, 25, 26],
#        [27, 28, 29, 30, 31, 32, 33, 34, 35]])

print(scramble(a, axis=1))

产量

[[ 3  8  7  0  4  5  1  2  6]
 [12 17 16  9 13 14 10 11 15]
 [21 26 25 18 22 23 19 20 24]
 [30 35 34 27 31 32 28 29 33]]

沿着0轴加扰:

print(scramble(a, axis=0))

产量

[[18 19 20 21 22 23 24 25 26]
 [ 0  1  2  3  4  5  6  7  8]
 [27 28 29 30 31 32 33 34 35]
 [ 9 10 11 12 13 14 15 16 17]]

首先使用最后一个轴交换目标轴:

b = a.swapaxes(axis, -1)

这是用于标准化处理一个轴的代码的常用技巧。 它将一般情况简化为处理最后一个轴的特定情况。 由于在NumPy版本1.10或更高版本swapaxes返回视图,因此不涉及复制,因此调用swapaxes非常快。

现在我们可以为最后一个轴生成一个新的索引顺序:

n = a.shape[axis]
idx = np.random.choice(n, n, replace=False)

现在我们可以随机播放b(独立于最后一个轴):

b = b[..., idx]

然后反转swapaxes以返回a形状的结果:

return b.swapaxes(axis, -1)

答案 1 :(得分:1)

上面的答案很好。但我会以一种快速而肮脏的方式抛出:

a = np.array([[1,2,3], [1,2,3], [1,2,3]])
ignore_list_outpput = [np.random.shuffle(x) for x in a]
Then, a can be something like this
array([[2, 1, 3],
       [4, 6, 5],
       [9, 7, 8]])

不是很优雅但你可以用一条短线完成这项工作。

答案 2 :(得分:1)

如果您不想要return值并希望直接对数组进行操作,则可以指定要随机播放的索引。

>>> import numpy as np
>>>
>>>
>>> a = np.array([[1,2,3], [1,2,3], [1,2,3]])
>>>
>>> # Shuffle row `2` independently
>>> np.random.shuffle(a[2])
>>> a
array([[1, 2, 3],
       [1, 2, 3],
       [3, 2, 1]])
>>>
>>> # Shuffle column `0` independently
>>> np.random.shuffle(a[:,0])
>>> a
array([[3, 2, 3],
       [1, 2, 3],
       [1, 2, 1]])

如果您还想要返回值,可以使用numpy.random.permutation,在这种情况下,将np.random.shuffle(a[n])替换为a[n] = np.random.permutation(a[n])

警告,请勿执行a[n] = np.random.shuffle(a[n])shuffle没有return任何内容,因此您最终“洗牌”的行/列将填充nan

答案 3 :(得分:0)

基于我对@Hun的回答的评论,这是最快的方法

def shuffle_along(X):
    """Minimal in place independent-row shuffler."""
    [np.random.shuffle(x) for x in X]

这可以就地工作,并且只能随机排列行。如果您需要更多选择:

def shuffle_along(X, axis=0, inline=False):
    """More elaborate version of the above."""
    if not inline:
        X = X.copy()
    if axis == 0:
        [np.random.shuffle(x) for x in X]
    if axis == 1:
        [np.random.shuffle(x) for x in X.T]
    if not inline:
        return X

但是,这有局限性,只能在二维数组上工作。对于高维张量,我将使用:

def shuffle_along(X, axis=0, inline=True):
    """Shuffle along any axis of a tensor."""
    if not inline:
        X = X.copy()
    np.apply_along_axis(np.random.shuffle, axis, X)  # <-- I just changed this
    if not inline:
        return X

答案 4 :(得分:0)

您可以使用numpy进行此操作,而无需任何循环或额外功能,并且速度更快。例如,我们有一个大小为(2,6)的数组,并且我们希望每个子列都具有独立的随机索引的子数组(2,2)。

import numpy as np

test = np.array([[1, 1],
                 [2, 2],
                 [0.5, 0.5],
                 [0.3, 0.3],
                 [4, 4],
                 [7, 7]])

id_rnd = np.random.randint(6, size=(2, 2))  # select random numbers, use choice and range if don want replacement.
new = np.take_along_axis(test, id_rnd, axis=0)

Out: 
array([[2. , 2. ],
       [0.5, 2. ]])

它适用于任何尺寸。