The issues here are:
- how a boolean indexing works
- how indexing lists (arrays) broadcast with each other
- how mixed advanced/basic indexing works.
In [286]: y1 = np.arange(18).reshape(3,2,3)
In [287]: y1
Out[287]:
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]],
[[12, 13, 14],
[15, 16, 17]]])
In [288]: y1[[0,1,2],:,[False, False, True]]
Out[288]:
array([[ 2, 5],
[ 8, 11],
[14, 17]])
In [289]: y1[[0,1,2],0:2,[False, False, True]]
Out[289]:
array([[ 2, 5],
[ 8, 11],
[14, 17]])
In [290]: y1[[0,1,2],[0,1],[False, False, True]]
....
IndexError: shape mismatch: indexing arrays could not be
broadcast together with shapes (3,) (2,) (1,)
So the first 2 produce a (3,2) result, and the last an error. Note that the last has converted the [False,False,True]
into a (1,) indexing array.
The first is the same as this simpler indexing:
In [294]: y1[:,:,2]
Out[294]:
array([[ 2, 5],
[ 8, 11],
[14, 17]])
If instead I use the boolean, it's as though I used y1[:,:,[2]]]
:
In [291]: y1[:,:,[False,False,True]]
Out[291]:
array([[[ 2],
[ 5]],
[[ 8],
[11]],
[[14],
[17]]])
A (3,2,1) array.
y1[np.ix_([0,1,2], [0,1], [2])]
produces the same thing, but with advanced indexing. The boolean list works in the same way. ix_
reshapes the 3 arrays so they can broadcast against each other
In [299]: np.ix_([0,1,2],[0,1],[2])
Out[299]:
(array([[[0]],
[[1]],
[[2]]]), array([[[0],
[1]]]), array([[[2]]]))
This creates a (3,1,1), (1,2,1), and (1,1,1) which broadcast to (3,2,1).
y1[[0,1,2], :, [2]]
also uses broadcasting, a (3,) with a (1,) to produce a (3,). The (2,) middle dimension is tacked on to the end. This an example of mixed basic/advanced indexing. In some cases this is counter intuitive. For example, y1[[2], :, [0,1,2]]
produces a (3,2), whereas users often expect (2,3).
Python multi-dimensional notation transpose automatically
The boolean indexing is not the same as a 0/1 indexing.
In [297]: y1[[0,1,2], :, [0,0,1]]
Out[297]:
array([[ 0, 3],
[ 6, 9],
[13, 16]])
This selects y1[0,:,0]
, y1[1,:,0]
, and y1[2,:,1]
. It pairs up the elements of the 2 lists. It broadcasts a (3,) with a (3,). Again the middle slice is added at the end.
Note that the boolean mask could have problems if it was [True, False, True]
, which is the equivalent of [0,2]
, a size (2,)
indexing. That does not broadcast with (3,)
.
In [307]: y1[[0,1,2],:,[True, False, True]]
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)
Test your understanding with y1[[[0],[1],[2]],:,[True, False, True]]
(3,2,2)
result, and
y1[[[0],[1],[2]],[0,1],[True, False, True]]
(3,2)
.