1

I have a 2D array A:

28  39  52
77  80  66   
7   18  24    
9   97  68

And a vector array of column indexes B:

1   
0   
2    
0

How, in a pythonian way, using base Python or Numpy, can I select the elements from A which DO NOT correspond to the column indexes in B?

I should get this 2D array which contains the elements of A, Not corresponding to the column indexes stored in B:

28  52
80  66   
7   18    
97  68
TylerH
  • 20,816
  • 57
  • 73
  • 92

2 Answers2

2

You can make use of broadcasting and a row-wise mask to select elements not contained in your array for each row:

Setup

B = np.array([1, 0, 2, 0])
cols = np.arange(A.shape[1])

Now use broadcasting to create a mask, and index your array.

mask = B[:, None] != cols
A[mask].reshape(-1, 2)

array([[28, 52],
       [80, 66],
       [ 7, 18],
       [97, 68]])
user3483203
  • 48,205
  • 9
  • 52
  • 84
1

A spin off of my answer to your other question,

Replace 2D array elements with zeros, using a column index vector

We can make a boolean mask with the same indexing used before:

In [124]: mask = np.ones(A.shape, dtype=bool)                                                                           
In [126]: mask[np.arange(4), B] = False                                                                                 
In [127]: mask                                                                                                          
Out[127]: 
array([[ True, False,  True],
       [False,  True,  True],
       [ True,  True, False],
       [False,  True,  True]])

Indexing an array with a boolean mask produces a 1d array, since in the most general case such a mask could select a different number of elements in each row.

In [128]: A[mask]                                                                                                       
Out[128]: array([28, 52, 80, 66,  7, 18, 97, 68])

In this case the result can be reshaped back to 2d:

In [129]: A[mask].reshape(4,2)                                                                                          
Out[129]: 
array([[28, 52],
       [80, 66],
       [ 7, 18],
       [97, 68]])

Since you allowed for 'base Python' here's list comprehension answer:

In [136]: [[y for i,y in enumerate(x) if i!=b] for b,x in zip(B,A)]                                                     
Out[136]: [[28, 52], [80, 66], [7, 18], [97, 68]]

If all the 0's in the other A come from the insertion, then we can also get the mask (Out[127]) with

In [142]: A!=0                                                                                                          
Out[142]: 
array([[ True, False,  True],
       [False,  True,  True],
       [ True,  True, False],
       [False,  True,  True]])
hpaulj
  • 201,845
  • 13
  • 203
  • 313