tommy.carstensen
tommy.carstensen

Reputation: 9622

Python - NumPy - deleting multiple rows and columns from an array

Let's say I have a square matrix as input:

array([[0, 1, 1, 0],
       [1, 1, 1, 1],
       [1, 1, 1, 1],
       [0, 1, 1, 0]])

I want to count the nonzeros in the array after removal of rows 2 and 3 and cols 2 and 3. Afterwards I want to do the same for rows 3 and 4 and cols 3 and 4. Hence the output should be:

0  # when removing rows/cols 2 and 3
3  # when removing rows/cols 3 and 4

Here is the naive solution using np.delete:

import numpy as np
a = np.array([[0,1,1,0],[1,1,1,1],[1,1,1,1],[0,1,1,0]])
np.count_nonzero(np.delete(np.delete(a, (1,2), axis=0), (1,2), axis=1))
np.count_nonzero(np.delete(np.delete(a, (2,3), axis=0), (2,3), axis=1))

But np.delete returns a new array. Is there a faster method, which involves deleting rows and columns simultaneously? Can masking be used? The documentation on np.delete reads:

Often it is preferable to use a boolean mask.

How do I go about doing that? Thanks.

Upvotes: 5

Views: 8354

Answers (2)

Bas Swinckels
Bas Swinckels

Reputation: 18488

Instead of deleting the columns and rows you don't want, it is easier to select the ones you do want. Also note that it is standard to start counting rows and columns from zeros. To get your first example, you thus want to select all elements in rows 0 and 3 and in rows 0 and 3. This requires advanced indexing, for which you can use the ix_ utility function:

In [25]: np.count_nonzero(a[np.ix_([0,3], [0,3])])  
Out[25]: 0

For your second example, you want to select rows 0 and 1 and columns 0 and 1, which can be done using basic slicing:

In [26]: np.count_nonzero(a[:2,:2])
Out[26]: 3

Upvotes: 5

rth
rth

Reputation: 11201

There is no need to modify your original array by deleting rows/columns, in order to count the number of non zero elements. Simply use indexing,

a = np.array([[0,1,1,0],[1,1,1,1],[1,1,1,1],[0,1,1,0]])
irows, icols = np.indices(a.shape)
mask = (irows!=2)&(irows!=3)&(icols!=2)&(icols!=3)
np.count_nonzero(a[mask])

Upvotes: 3

Related Questions