2

I have a matrix [n x 3]. I want to specify row:
test_row = np.array([a, b, c])
and delete it from my matrix.

Is there a better way than using for and np.array_equal over whole matrix?

vestapas
  • 21
  • 1
  • Why is `np.array_equal` not good enough? – DYZ Mar 19 '19 at 23:44
  • 1
    Possible duplicate of [deleting rows in numpy array](https://stackoverflow.com/questions/3877491/deleting-rows-in-numpy-array) – Leonid Mar 19 '19 at 23:46
  • I am curious is there 'numpy way' to do it. Without iterating over whole matrix with for. – vestapas Mar 19 '19 at 23:46
  • So you want the array without the row that matches `test_row`? Could there be more than one such row? You want an exact match? – hpaulj Mar 20 '19 at 01:51

2 Answers2

0

An alternative to deleting the desired rows is, if you happen to know the index of the row that you want to remove, you can simply slice the remaining rows and concatenate it into a matrix as in the example below:

In [8]: arr = np.arange(5*3).reshape(5, 3)

In [9]: arr
Out[9]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11],
       [12, 13, 14]])

In [10]: remove_row_idx = 2

In [11]: np.vstack((arr[:remove_row_idx, :], arr[remove_row_idx+1:,]))
Out[11]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 9, 10, 11],
       [12, 13, 14]])
kmario23
  • 57,311
  • 13
  • 161
  • 150
  • I only know values of `[(a, b, c)]` I found this solution: https://stackoverflow.com/a/18927811/11229272 but I thought there will be a straightforward solution to deleting rows with given values. – vestapas Mar 20 '19 at 00:16
0
In [318]: arr = np.arange(24).reshape(8,3)                                                
In [319]: test = np.array([6,7,8])                                                        

A whole-array comparison between the 2:

In [322]: np.isin(arr,test)                                                               
Out[322]: 
array([[False, False, False],
       [False, False, False],
       [ True,  True,  True],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False]])

Find the row where all terms match:

In [323]: np.isin(arr,test).all(axis=1)                                                   
Out[323]: array([False, False,  True, False, False, False, False, False])

Use its inverse as the mask to select the keeper rows:

In [324]: arr[~_]                                                                         
Out[324]: 
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 9, 10, 11],
       [12, 13, 14],
       [15, 16, 17],
       [18, 19, 20],
       [21, 22, 23]])

isin actually is in1d plus a reshape:

In [327]: np.in1d(arr,test)                                                               
Out[327]: 
array([False, False, False, False, False, False,  True,  True,  True,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False])
In [328]: np.in1d(arr,test).reshape(arr.shape)                                            
Out[328]: 
array([[False, False, False],
       [False, False, False],
       [ True,  True,  True],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False],
       [False, False, False]])

This broadcasted comparison also works:

(arr[:,None,:]==test[None,:,None]).any(axis=1).all(axis=1)
hpaulj
  • 221,503
  • 14
  • 230
  • 353