Pete
Pete

Reputation: 2344

Numpy advanced indexing, bool vs. int IndexError: too many indices for array

Trying to use numpy advanced indexing into a matrix - https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html

This works as expected, returning the whole matrix, v

import numpy as np
v = np.reshape(np.arange(0,9), (3,3))
v[np.asarray([0,1,2])[:,np.newaxis], np.asarray([0,1,2])]

Using logical indexing also works as expected:

v[np.asarray([0,1,2])[:,np.newaxis], np.asarray([True, True, True])]

Surprisingly (to me, at least), this errors when switching the order of the index vectors?

v[np.asarray([True, True, True])[:,np.newaxis], np.asarray([0,1,2])]

Or if both vectors are boolean

v[np.asarray([True, True, True])[:,np.newaxis], np.asarray([True, True, True])]

With the error "*** IndexError: too many indices for array". I expected the 3rd and 4th examples to work just like the 1st and 2nd. What am I missing?

Upvotes: 0

Views: 149

Answers (1)

hpaulj
hpaulj

Reputation: 231385

https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#boolean-array-indexing

the last part of this boolean indexing section says you need to use np.ix_ to generate the relevant indices. It converts the boolean in to equivalent nonzero indices. Broadcasting does not work with boolean arrays

In [48]: np.ix_(np.asarray([True, True, True]), np.asarray([0,1,2]))            
Out[48]: 
(array([[0],
        [1],
        [2]]), array([[0, 1, 2]]))

ix_ generates the correct array indices to perform the block indexing:

In [50]: v[np.ix_(np.asarray([True, True, True]), np.asarray([0,1,2]))]         
Out[50]: 
array([[0, 1, 2],
       [3, 4, 5],
       [6, 7, 8]])

The same arrays without ix select the diagonal:

In [51]: v[np.asarray([True, True, True]), np.asarray([0,1,2])]                 
Out[51]: array([0, 4, 8])

Assuming boolean indexing is done with some form of np.where/nonzero, it's possible that this 2d nonzero result is giving the indexing error. But it's occurring in compiled code so it's hard to trace the details:

In [53]: np.asarray([True, True, True])[:,np.newaxis].nonzero()                 
Out[53]: (array([0, 1, 2]), array([0, 0, 0]))

We can index with a boolean that matches v in shape, but the result is 1d:

In [66]: np.array([True,True,True])[:,None].repeat(3,1)                         
Out[66]: 
array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]])
In [67]: v[_]                                                                   
Out[67]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])

Upvotes: 1

Related Questions