Numpy: shuffle subset of elements Numpy: shuffle subset of elements numpy numpy

Numpy: shuffle subset of elements


You can use np.random.permutation to get a shuffled copy of an input sequence, and then assign this using indexing:

In [19]: a = np.arange(16).reshape((4,4))In [20]: aOut[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]: aOut[22]:array([[12,  1,  2, 15],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11],       [ 0, 13, 14,  3]])

Also, you can get a view of the 4 corners of your array using a[::a.shape[0]-1, ::a.shape[1]-1]

However, since the result from that is a two-dimensional numpy array, shuffling will only shuffle along the first axis.


The culprit is that np.random.shuffle does change the array in-place and never returns a value, ordering the entries randomly. Your code changes the new and temporary array containing the corners, which is changed, but you have no reference to it, so you see no changes. Check out:

>>> import numpy as np >>> a = np.arange(16).reshape((4,4))>>> aarray([[ 0,  1,  2,  3],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11],       [12, 13, 14, 15]])>>> np.random.shuffle(a)>>> aarray([[12, 13, 14, 15],       [ 4,  5,  6,  7],       [ 8,  9, 10, 11],       [ 0,  1,  2,  3]])>>> np.random.shuffle(a)>>> aarray([[ 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)>>> barray([ 0, 11,  8,  3])>>>  

Now you just have to reassign the corners using b. And take care, the corners in my example were taken from the already shuffled array a.