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
2
  • Use arange: arr[np.arange(arr.shape[0]), cols-1] Commented Sep 29, 2018 at 20:17
  • fyi; python arrays are 0 based. so B should be [1,0,2,0] to get your desired output. [A[i][B[i]] for i in range(len(A))] is what you want in plain python. Commented Sep 29, 2018 at 20:24

2 Answers 2

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]])
Sign up to request clarification or add additional context in comments.

Comments

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]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.