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?

+3


source to share


2 answers


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) enter image description here



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]])

      

+1


source


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 ( ...

), or np.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 item

In 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.

+5


source







All Articles