<div dir="ltr"><div><div>I created an issue on github for an enhancement<br>to numpy.random.shuffle:<br>    <a href="https://github.com/numpy/numpy/issues/5173">https://github.com/numpy/numpy/issues/5173</a><br>I'd like to get some feedback on the idea.<br><br>Currently, `shuffle` shuffles the first dimension of an array<br>in-place.  For example, shuffling a 2D array shuffles the rows:<br><br><span style="font-family:courier new,monospace">In [227]: a<br>Out[227]: <br>array([[ 0,  1,  2],<br>       [ 3,  4,  5],<br>       [ 6,  7,  8],<br>       [ 9, 10, 11]])<br><br>In [228]: np.random.shuffle(a)<br><br>In [229]: a<br>Out[229]: <br>array([[ 0,  1,  2],<br>       [ 9, 10, 11],<br>       [ 3,  4,  5],<br>       [ 6,  7,  8]])</span><br><br><br>To add an axis keyword, we could (in effect) apply `shuffle` to<br>`a.swapaxes(axis, 0)`.  For a 2-D array, `axis=1` would shuffles<br>the columns:<br><span style="font-family:courier new,monospace"><br>In [232]: a = np.arange(15).reshape(3,5)<br><br>In [233]: a<br>Out[233]: <br>array([[ 0,  1,  2,  3,  4],<br>       [ 5,  6,  7,  8,  9],<br>       [10, 11, 12, 13, 14]])<br><br>In [234]: axis = 1<br><br>In [235]: np.random.shuffle(a.swapaxes(axis, 0))<br><br>In [236]: a<br>Out[236]: <br>array([[ 3,  2,  4,  0,  1],<br>       [ 8,  7,  9,  5,  6],<br>       [13, 12, 14, 10, 11]])</span><br><br>So that's the first part--adding an `axis` keyword.<br><br>The other part of the enhancement request is to add a shuffle<br>behavior that shuffles the 1-d slices *independently*.  That is,<br>for a 2-d array, shuffling with `axis=0` would apply a different<br>shuffle to each column.  In the github issue, I defined a<br>function called `disarrange` that implements this behavior:<br><br><span style="font-family:courier new,monospace">In [240]: a<br>Out[240]: <br>array([[ 0,  1,  2],<br>       [ 3,  4,  5],<br>       [ 6,  7,  8],<br>       [ 9, 10, 11],<br>       [12, 13, 14]])<br><br>In [241]: disarrange(a, axis=0)<br><br>In [242]: a<br>Out[242]: <br>array([[ 6,  1,  2],<br>       [ 3, 13, 14],<br>       [ 9, 10,  5],<br>       [12,  7,  8],<br>       [ 0,  4, 11]])</span><br><br>Note that each column has been shuffled independently.<br><br>This behavior is analogous to how `sort` handles the `axis`<br>keyword.  `sort` sorts the 1-d slices along the given axis<br>independently.<br><br>In the github issue, I suggested the following signature<br>for `shuffle` (but I'm not too fond of the name `independent`):<br><br><span style="font-family:courier new,monospace">  def shuffle(a, independent=False, axis=0)</span><br><br>If `independent` is False, the current behavior of `shuffle`<br>is used.  If `independent` is True, each 1-d slice is shuffled<br>independently (in the same way that `sort` sorts each 1-d<br>slice).<br><br>Like most functions that take an `axis` argument, `axis=None`<br>means to shuffle the flattened array.  With `independent=True`,<br>it would act like `np.random.shuffle(a.flat)`, e.g.<br><span style="font-family:courier new,monospace"><br>In [247]: a<br>Out[247]: <br>array([[ 0,  1,  2,  3,  4],<br>       [ 5,  6,  7,  8,  9],<br>       [10, 11, 12, 13, 14]])<br><br>In [248]: np.random.shuffle(a.flat)<br><br>In [249]: a<br>Out[249]: <br>array([[ 0, 14,  9,  1, 13],<br>       [ 2,  8,  5,  3,  4],<br>       [ 6, 10,  7, 12, 11]])</span><br><br><br>A small wart in this API is the meaning of<br><br><span style="font-family:courier new,monospace">  shuffle(a, independent=False, axis=None)</span><br><br>It could be argued that the correct behavior is to leave the<br></div></div>array unchanged. (The current behavior can be interpreted as<br>shuffling a 1-d sequence of monolithic blobs; the axis argument<br>specifies which axis of the array corresponds to the<br>sequence index.  Then `axis=None` means the argument is<br>a single monolithic blob, so there is nothing to shuffle.)<br>Or an error could be raised.<br><div><div><br>What do you think?<br><br>Warren<br><br></div></div></div>