Reputation: 2344
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
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