Numpy:洗牌元素的子集

Numpy: shuffle subset of elements

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

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

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,我发现上面使用了高级切片,returns一个副本,而不是一个视图。 但是这个副本是就地打乱的,所以没有结果分配给原始数组。

所以问题是,如何排列所选索引的元素?

您可以使用 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 数组,因此洗牌只会沿第一个轴洗牌。

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

>>> 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.

中取出的