Zidan
Zidan

Reputation: 135

Numpy call array values by list of indices

I have a 2D array of values, and I want to call it by two list of indices x,y. It used to work perfect before, I don't know why it's not working now, maybe python version, not sure.

x = np.squeeze(np.where(data['info'][:,2]==cdp)[0])
y = np.squeeze(np.where((data['Time']>=ub) & (data['Time']<=lb))[0])

s = data['gather'][x,y]

Error:

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (36,) (45,) 

I don't what is the problem. It works when I do it in two stages.

s = data['gather'][:,y]; s = s[x,:]

But, I can't do this, I need to do at one run

Upvotes: 0

Views: 50

Answers (1)

hpaulj
hpaulj

Reputation: 231355

In [92]: data = np.arange(12).reshape(3,4)                                                                           
In [93]: x,y = np.arange(3), np.arange(4)                                                                            
In [94]: data[x,y]                                                                                                   
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-94-8bd18da6c0ef> in <module>
----> 1 data[x,y]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (4,) 

When you provide 2 or more arrays as indices, numpy broadcasts them against each other. Understanding broadcasting is important.

In MATLAB providing two indexing arrays (actually 2d matrices) fetches a block. In numpy, to arrays, if they match in shape, fetch elements, e.g. a diagonal:

In [99]: data[x,x]                                                                                                   
Out[99]: array([ 0,  5, 10])

The MATLAB equivalent requires an extra function, 'indices to sub' or some such name.

Two stage indexing:

In [95]: data[:,y][x,:]                                                                                              
Out[95]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

ix_ is a handy tool for constructing indices for block access:

In [96]: data[np.ix_(x,y)]                                                                                           
Out[96]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Notice what it produces:

In [97]: np.ix_(x,y)                                                                                                 
Out[97]: 
(array([[0],
        [1],
        [2]]), array([[0, 1, 2, 3]]))

that's the same as doing:

In [98]: data[x[:,None], y]                                                                                          
Out[98]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

x[:,None] is (3,1), y is (4,); they broadcast to produce a (3,4) selection.

Upvotes: 1

Related Questions