Multidimensional numpy array indexing depends on slicing method
I have a 3D array. When I take the 2nd slice, the result depends on whether it is indexed by a list or a slice. In the first case, the result is transposed. Couldn't find this behavior in the manual .
>>> import numpy as np
>>> x = np.array([[[1,1,1],[2,2,2]], [[3,3,3],[4,4,4]]])
>>> x
array([[[1, 1, 1],
[2, 2, 2]],
[[3, 3, 3],
[4, 4, 4]]])
>>> x[0,:,[0,1]]
array([[1, 2],
[1, 2]])
>>> x[0,:,slice(2)]
array([[1, 1],
[2, 2]])
>>>
Can anyone point out this rationale?
source to share
As I understand it, NumPy follows the axis numbering philosophy where it spits out the result at a given index list/tuple
.
array([[[1, 1, 1],
[2, 2, 2]],
[[3, 3, 3],
[4, 4, 4]]])
When you already specify the first two indices ( x[0, :, ]
), now the next question is how to extract the third dimension. Now when you specify a tuple (0,1)
it first pops the 0
th axis slice wise, so it gets [1, 2]
as it lies in the 0
th axis, then it pops 1
st slice similarly and stacks below the already existing row [1, 2]
.
[[1, 1, 1], array([[1, 2],
[2, 2, 2]] =====> [1, 2]])
(render this structure as below (not on top) of an already existing row, as the -0 axis grows downward)
Alternatively, it follows the slice philosophy ( start
: stop
:) step
when specified for an index slice(n)
. Note that the usage slice(2)
is essentially equal 0:2
in your example. So, it extracts first [1, 1]
, then [2, 2]
. Notice how it [1, 1]
appears above [2, 2]
, again following the same axis philosophy that we have not yet left the third dimension. This is why this result is a transposition of the other.
array([[1, 1],
[2, 2]])
Also note that starting with 3D arrays, this sequence is preserved. Below is an example from array 4-D
and cutting results.
In [327]: xa
Out[327]:
array([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],
[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]],
[[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]],
[[27, 28, 29],
[30, 31, 32],
[33, 34, 35]]]])
In [328]: xa[0, 0, :, [0, 1]]
Out[328]:
array([[0, 3, 6],
[1, 4, 7]])
In [329]: xa[0, 0, :, 0:2]
Out[329]:
array([[0, 1],
[3, 4],
[6, 7]])
source to share
Since you are using advanced indexing when using [0,1]
. From the docs :
Combining advanced and basic indexing
When there is at least one slice (:
), ellipsis (...
), ornp.newaxis
index (or the array is larger than the advanced indexes), then the behavior can be more complex. This is like concatenating the indexing result for each promoted index itemIn the simplest case, there is only one extended index. One extended index could, for example, replace a slice and the result array would be the same, however it is a copy and may have a different memory layout . A slice is preferred if possible.
Note the two parts highlighted above.
In particular, in this construction:
>>> x[0,:,[0,1]]
array([[1, 2],
[1, 2]])
This is the case when the index contains at least one "slice, ellipsis, or np.newaxis", and the behavior is similar , concatenating the result of the indexing for each advanced element of the index . So:
>>> x[0,:,[0]]
array([[1, 2]])
>>> x[0,:,[1]]
array([[1, 2]])
>>> np.concatenate((x[0,:,[0]], x[0,:,[1]]))
array([[1, 2],
[1, 2]])
However, this construct is similar to the simple case: there is only one extended index, so it acts like a slice:
>>> x[0,:,slice(2)]
array([[1, 1],
[2, 2]])
>>> x[slice(0,1),:,slice(2)]
array([[[1, 1],
[2, 2]]])
Although note that the later version is actually 3-D because the first part of the index was acting like a slice, it is 3 slices, so three dimensions.
source to share