# [Numpy-discussion] Fancy indexing oddity

Sebastian Berg sebastian at sipsolutions.net
Wed Jul 3 03:52:16 EDT 2013

```On Tue, 2013-07-02 at 20:44 -0700, Bradley M. Froehle wrote:
> A colleague just showed me this indexing behavior and I was at a loss
> to explain what was going on.  Can anybody else chime in and help me
> understand this indexing behavior?
>
>     >>> import numpy as np
>     >>> np.__version__
>     '1.7.1'
>     >>> A = np.ones((2,3,5))
>     >>> mask = np.array([True]*4 + [False], dtype=bool)
>     >>> A.shape
>     (2, 3, 5)
>     (2, 3, 4)
>     (2, 4)
>     (4, 3) # Why is this not (3, 4)?
>     (3, 4)
>

Numpy has slicing and fancy indexing. But scalars are both. They are
fancy indexes, but they do not trigger fancy indexing (you could also
add the special case of a scalar result to this, but it doesn't matter
for this)!
Implementation wise mixed fancy indexing/slicing is a multi step
process:

1. Evaluate the slices. (no surprises here)
2. Evaluate the fancy indexing moving the new axes to the *front*. Here
this means A[1,:,mask] -> A.transpose(2,0,1) then combining all fancy
indexes so that A.shape goes from (2, 3, 5) via transpose (5,2,3) to
(4,3), since the combination of 1 and mask gives a 1-d result with 4
entries.
3. If and only if all fancy indexes were consecutive, i.e. A[:,1,mask],
A[mask,[],:], numpy can basically guess where it would make sense to
put the fancy axes. So it transposes it back. This is what makes a
single fancy index behave like a slice. Now in your example A[1,:,mask]
is *not* consecutive (remember scalars are fancy in this regard), so the
fancy axis goes to the front instead of going to where "mask" was.

In short, the resulting axes from the fancy indices is at the front if
the fancy indices are not consecutive. And since scalars are considered
fancy in this regard they are not consecutive in your example.

- Sebastian

> Thanks!