Bar Bar - 2 months ago 13
Python Question

numpy - Shuffling non-zero elements of each row in an array

I have a an array that is relatively sparse, and I would like to go through each row and shuffle only the non-zero elements.

Example Input:

[2,3,1,0]
[0,0,2,1]


Example Output:

[2,1,3,0]
[0,0,1,2]


Note how the zeros have not changed position.

To shuffle all elements in each row (including zeros) I can do this:

for i in range(len(X)):
np.random.shuffle(X[i, :])


What I tried to do then is this:

for i in range(len(X)):
np.random.shuffle(X[i, np.nonzero(X[i, :])])


But it has no effect. I've noticed that the return type of
X[i, np.nonzero(X[i, :])]
is different from
X[i, :]
which might be the
cause.

In[30]: X[i, np.nonzero(X[i, :])]
Out[30]: array([[23, 5, 29, 11, 17]])

In[31]: X[i, :]
Out[31]: array([23, 5, 29, 11, 17])

Answer Source

You could use the non-inplace numpy.random.permutation with explicit non-zero indexing:

>>> X = np.array([[2,3,1,0], [0,0,2,1]])
>>> for i in range(len(X)):
...     idx = np.nonzero(X[i])
...     X[i][idx] = np.random.permutation(X[i][idx])
... 
>>> X
array([[3, 2, 1, 0],
       [0, 0, 2, 1]])