Python Numpy:洗牌元素的子集

Python Numpy:洗牌元素的子集,python,numpy,shuffle,Python,Numpy,Shuffle,我有一个二维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]]) 数组没有更改。阅读时,我发现上面使用的是高

我有一个二维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]])
数组没有更改。阅读时,我发现上面使用的是高级切片,它返回的是一个副本,而不是视图。 但是,该副本会在适当的位置进行洗牌,因此不会将结果分配给原始数组

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

您可以使用获取输入序列的无序副本,然后使用索引分配:

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]


但是,由于这是一个二维numpy数组,因此洗牌只会沿着第一个轴进行。

罪魁祸首是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中提取的。

当我试图在中间部分使用
shuffle
时,也出现了仅洗牌1维的问题,但是
permutation
对于
np.random.permutation(a[1:-1,1:-1])
,所以我也会尝试高级索引。Numpy索引需要一段时间才能掌握窍门,但是非常非常强大。快乐编程!你的代码确实解决了这个问题。然而,看起来这只是
np.random.permutation
(如果我错了,请纠正我)的更明确/详细的版本。根据文档中的描述,有更微妙的区别:permutation在执行洗牌之前复制数组和子数组。还有一种方便的方法
np.random.permutation(n)
生成一个数字从0到n的随机数组。请参阅[和文档中的上一主题。在您的情况下,这并不重要,因为您仅排列选定的角点并重新分配它们。