【问题标题】:Numpy: shuffle subset of elementsNumpy:随机播放元素的子集
【发布时间】:2018-04-26 18:54:38
【问题描述】:

我有一个二维 numpy 数组,将其解释为一个网格,并且想要置换元素的一个子集。 更准确地说,一条边映射到一条边,一个角映射到一个角。

  • np.random.shuffle 可以完成这项工作,只要元素的任何排列都可以。

我可以通过以下方式进入角落:

a = np.arange(16).reshape((4,4))
a[[0,0,-1,-1],[0,-1,0,-1]]

但是,当我打电话时

np.random.shuffle(a[[0,0,-1,-1],[0,-1,0,-1]])

数组没有改变。阅读https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html,我发现上面使用了Advanced Slicing,它返回一个副本,而不是一个视图。 但是这个副本是原地洗牌的,所以没有结果要分配给原始数组。

所以问题是,我如何置换所选索引的元素?

【问题讨论】:

    标签: python numpy shuffle


    【解决方案1】:

    您可以使用np.random.permutation 获取输入序列的随机副本,然后使用索引对其进行分配:

    In [19]: a = np.arange(16).reshape((4,4))
    
    In [20]: a
    Out[20]:
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    
    In [21]: a[[0,0,-1,-1],[0,-1,0,-1]] = np.random.permutation(a[[0,0,-1,-1],[0,-1,0,-1]])
    
    In [22]: a
    Out[22]:
    array([[12,  1,  2, 15],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [ 0, 13, 14,  3]])
    

    此外,您可以使用 a[::a.shape[0]-1, ::a.shape[1]-1]

    获得阵列 4 个角的视图

    但是,由于它的结果是一个二维 numpy 数组,因此洗牌只会沿第一个轴洗牌。

    【讨论】:

    • 这个问题也出现了,只有1维洗牌,当我尝试在中心部分使用shuffle,但permutation也有这个问题np.random.permutation(a[1:-1,1:-1]),所以我会尝试高级也在那里建立索引。
    • Numpy 索引需要一段时间才能掌握,但非常非常强大。编程愉快!
    【解决方案2】:

    罪魁祸首是 np.random.shuffle 确实就地更改了数组并且从不返回值,随机排序条目。您的代码更改了包含角的新临时数组,该数组已更改,但您没有引用它,因此您看不到任何更改。签出:

    >>> import numpy as np 
    >>> a = np.arange(16).reshape((4,4))
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [12, 13, 14, 15]])
    >>> np.random.shuffle(a)
    >>> a
    array([[12, 13, 14, 15],
           [ 4,  5,  6,  7],
           [ 8,  9, 10, 11],
           [ 0,  1,  2,  3]])
    >>> np.random.shuffle(a)
    >>> a
    array([[ 0,  1,  2,  3],
           [ 4,  5,  6,  7],
           [12, 13, 14, 15],
           [ 8,  9, 10, 11]])
    >>> a[[0,0,-1,-1],[0,-1,0,-1]]
    array([ 0,  3,  8, 11])
    >>> np.random.shuffle(a[[0,0,-1,-1],[0,-1,0,-1]])
    >>> b = a[[0,0,-1,-1],[0,-1,0,-1]]
    >>> np.random.shuffle(b)
    >>> b
    array([ 0, 11,  8,  3])
    >>>  
    

    现在您只需使用 b 重新分配角点。请注意,我的示例中的角是从已经洗牌的数组 a 中取出的。

    【讨论】:

    • 您的代码确实解决了问题。但是,看起来这只是np.random.permutation 的更明确/更详细的版本(如果我错了,请纠正我)。
    • 根据文档有更细微的区别:
    • 置换在改组之前执行置换之前复制数组和子数组。还有一种方便的方法np.random.permutation(n) 可以生成一个从0到n的随机数组。请参阅 [docs.scipy.org/doc/numpy/reference/generated/… 和文档中的上一个主题。在您的情况下,这并不重要,因为您只排列选定的角并重新分配它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 2016-10-07
    • 2014-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多