Indexing a NumPy 2D Array with Another 2D Array

I have something like

m = array([[1, 2], [4, 5], [7, 8], [6, 2]]) 

and

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

My goal

 result = array([1, 5, 7, 6]) 

I tried _ ix when I read in the Simplfy row and fetching the column, numpy , but that did not lead to what I wanted.

ps Please change the name of this question if you can think of a more accurate one.

+4
source share
6 answers

How about using python?

 result = array([subarray[index] for subarray, index in zip(m, select)]) 
+1
source

The numpy way to do this is to use np.choose or fancy indexing / accepting (see below):

 m = array([[1, 2], [4, 5], [7, 8], [6, 2]]) select = array([0,1,0,0]) result = np.choose(select, mT) 

This way there is no need for python loops or anything else, with all the speed advantages numpy gives you. mT simply necessary because the choice is really more than the choice between the two arrays np.choose(select, (m[:,0], m[:1])) , but its direct way to use it like this.


Using fantasy indexing:

 result = m[np.arange(len(select)), select] 

And if speed is very important, np.take , which works on a 1D representation (for some reason, it's a little faster, but maybe not for these tiny arrays):

 result = m.take(select+np.arange(0, len(select) * m.shape[1], m.shape[1])) 
+10
source

I prefer using NP.where for this type of indexing task (rather than NP.ix _)

What is not specified in the OP is whether the result is selected by location (string / col in the original array) or by some condition (for example, m> = 5). In any case, the code snippet below covers both scenarios.

Three steps:

  • create an array ;

  • generate the index array by calling NP.where, passing in this an array of conditions; and

  • apply this index array to the original array


 >>> import numpy as NP >>> cnd = (m==1) | (m==5) | (m==7) | (m==6) >>> cnd matrix([[ True, False], [False, True], [ True, False], [ True, False]], dtype=bool) >>> # generate the index array/matrix >>> # by calling NP.where, passing in the condition (cnd) >>> ndx = NP.where(cnd) >>> ndx (matrix([[0, 1, 2, 3]]), matrix([[0, 1, 0, 0]])) >>> # now apply it against the source array >>> m[ndx] matrix([[1, 5, 7, 6]]) 


The argument passed to NP.where, cnd, is a Boolean array, which in this case is the result of a single expression consisting of compound conditional expressions (first line above)

If building such a value filter is not your specific use case, that’s fine, you just need to generate the actual logical matrix ( cnd value) in some other way (or create it directly).

+2
source

Since the title refers to indexing a 2D array with another 2D array, you can find a general numpy solution here .

In short: a 2D array of form indices (n, m) with an arbitrary large dimension m named inds is used to access the elements of another 2D array of form (n, k) named B :

 # array of index offsets to be added to each row of inds offset = np.arange(0, inds.size, inds.shape[1]) # numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C Result = np.take(B, offset[:,np.newaxis]+inds) 
+1
source
 result = array([m[j][0] if i==0 else m[j][1] for i,j in zip(select, range(0, len(m)))]) 
0
source

IMHO, this is the easiest option:

 m[np.arange(4), select] 
0
source

Source: https://habr.com/ru/post/1403604/


All Articles