Search code examples
pythonnumpymultidimensional-arrayindexingslice

Why the result is different? Numpy Slicing and indexing


Basically I want to obtain a part of the variable "cubote". I tried two methods that should work in the same way, but it didn't.

My code:

   import numpy as np

   # Create a 3x3x3 cube
   cubote = np.arange(27).reshape(3,3,3)

   # Compare the results
   result1 = cubote[0:2,0:2,0:2]
   result2 = cubote[0:2][0:2][0:2]

   print(result1)
   print("Shape of result1:", result1.shape)

   print(result2)
   print("Shape of result2:", result2.shape)

OUTPUT:

result1:

   [[[ 0  1]
     [ 3  4]]

    [[ 9 10]
     [12 13]]]
   Shape of result1: (2, 2, 2)

result2:

   [[[ 0  1  2]
     [ 3  4  5]
     [ 6  7  8]]

    [[ 9 10 11]
     [12 13 14]
     [15 16 17]]]
   Shape of result2: (2, 3, 3)

I expected the two results to be the same.

I refer to the result 1 makes sense, but result 2 did not work as I expected.

WHY?


Solution

  • The difference in the results between result1 and result2 comes down to how indexing works in NumPy.

    Explanation of result1:

    result1 = cubote[0:2, 0:2, 0:2]
    

    In this case, you are applying slicing across all three dimensions at once. This means you are extracting a sub-cube with indices in the ranges [0:2] in all three dimensions, which gives you a 2x2x2 cube.

    Explanation of result2:

    result2 = cubote[0:2][0:2][0:2]
    

    Here, you're doing something different. Let’s break it down:

    1.cubote[0:2] extracts the first two "layers" (2D arrays) from the cube, so the result of this step is:

    array([[[ 0,  1,  2],
            [ 3,  4,  5],
            [ 6,  7,  8]],
    
           [[ 9, 10, 11],
            [12, 13, 14],
            [15, 16, 17]]])
    

    This is a 2x3x3 array.

    1. Then, [0:2] is applied to this result, which further extracts the first two rows (along the first axis) of the new array. But since the array is already 2x3x3, this doesn’t reduce the size, and you still have a 2x3x3 array.

    2. Finally, [0:2] is applied again, but since you're now operating on the first axis of the current 2D slices (each of shape 3x3), it doesn't behave as expected because you've already "peeled off" dimensions.

    Key Difference:

    1. Slicing across all dimensions at once (as in result1) extracts the correct sub-cube.

    2. Chained indexing (as in result2) performs indexing sequentially, and since each index slice operates on the current result rather than on all dimensions at once, you don't get the same shape or result.

    You should use slicing in all dimensions simultaneously, like in result1, to obtain the expected 2x2x2 sub-cube.

    cubote[0:2, 0:2, 0:2]: Extracts a sub-cube across all three dimensions.

    cubote[0:2][0:2][0:2]: Extracts slices sequentially, leading to an unexpected result.

    To get consistent results, always apply slicing across all dimensions at once if you are trying to extract a subarray.