Delete both row and column in numpy array

Viewed 851

Say I have an array like this:

x = [1, 2, 3]
    [4, 5, 6]
    [7, 8, 9]

And I want to delete both the ith row and column. So if i=1, I'd create (with 0-indexing):

[1, 3]
[7, 9]

Is there an easy way of doing this with a one-liner? I know I can call np.delete() twice, but that seems a little unclean.

It'd be exactly equivalent to np.delete(np.delete(x, idx, 0), idx, 1), where idx is the index of the row/column pair to delete - it'd just look cleaner.

2 Answers

This can be easily achieved by numpy's delete function. It would be:

arr = np.delete(arr, index, 0) # deletes the desired row 
arr = np.delete(arr, index, 1) # deletes the desired column at index

The third argument is the axis.

In [196]: x = np.arange(1,10).reshape(3,3)

If you look at np.delete code, you'll see that it's python (not compiled) and takes different approaches depending on how the delete values are specified. One is to make a res array of right size, and copy two slices to it.

Another is to make a boolean mask. For example:

In [197]: mask = np.ones(x.shape[0], bool)
In [198]: mask[1] = 0
In [199]: mask
Out[199]: array([ True, False,  True])

Since you are deleting the same row and column, use this indexing:

In [200]: x[mask,:][:,mask]
Out[200]: 
array([[1, 3],
       [7, 9]])

A 1d boolean mask like this can't be 'broadcasted' in the same ways a integer array can.

We can do the 2d advanced indexing with:

In [201]: idx = np.nonzero(mask)[0]
In [202]: idx
Out[202]: array([0, 2])
In [203]: np.ix_(idx,idx)
Out[203]: 
(array([[0],
        [2]]),
 array([[0, 2]]))
In [204]: x[np.ix_(idx,idx)]
Out[204]: 
array([[1, 3],
       [7, 9]])

Actually ix_ can work directly from the boolean array(s):

In [207]: np.ix_(mask,mask)
Out[207]: 
(array([[0],
        [2]]),
 array([[0, 2]]))

This isn't a one-liner, but it probably is faster than the double delete, since it strips off all the extra baggage that the more general function requires.

Related