CEFOG
CEFOG

Reputation: 89

Remove certain value from matrix

I want to remove all zeros from a matrix, so each row or column containing zero will be removed. Like this: the input is this matrix:

np.array([
     [1, 2, 3, 4, 5],
     [6, 0, 8 ,9,10],
    [11,12,13,14,15],
    [16, 0, 0,19,20]])

The three zeros should cause rows 1 & 3 (zero-based indexing) and columns 1 & 2 to get deleted. The output matrix shall be:

np.array([
    [ 1, 4, 5],
    [11,14,15]])

So far I´ve tried this:

for i in range(0,len(Matrix)):
    Matrix[Matrix[:,i]!=0]
for i in range(len(Matrix),0):
    Matrix[Matrix[i,:]!=0]

Upvotes: 1

Views: 82

Answers (2)

DSM
DSM

Reputation: 353249

You could use np.ix_ to handle the indexing magic:

In [26]: arr = np.array([[1,2,3,4,5],[6,0,8,9,10],[11,12,13,14,15],[16,0,0,19,20]])

In [27]: mask = arr != 0

In [28]: arr[np.ix_(mask.all(1), mask.all(0))]
Out[28]: 
array([[ 1,  4,  5],
       [11, 14, 15]])

The indexing magic in question is that np.ix_ will turn the boolean arrays into the right indices for each axis:

In [29]: mask.all(1)
Out[29]: array([ True, False,  True, False])

In [30]: mask.all(0)
Out[30]: array([ True, False, False,  True,  True])

In [31]: np.ix_(mask.all(1), mask.all(0))
Out[31]: 
(array([[0],
        [2]]), array([[0, 3, 4]]))

which really isn't so magical at all, it's effectively

In [34]: np.arange(len(mask.all(1)))[mask.all(1)]
Out[34]: array([0, 2])

behind the scenes.

Upvotes: 3

Prune
Prune

Reputation: 77867

The problem with your initial approach is that the first loop removes all rows with zeros. When you get to the second loop, there are no zeros remaining, and no clues about where they were, so you can't remove any columns.

in that first loop, instead of removing the row, set all non-zero entries to NaN or some other "marker" value. Then remove every columns with a zero. Finally, come back and remove the rows with NaN.

Upvotes: 1

Related Questions