0

I am trying various ways for slicing a numpy arrray. I thought that both the print statements will yield the same output. But they are not. Can anyone explain me why?

import numpy as np
two_dim_array = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
print(two_dim_array)
print(two_dim_array[[0,1],[2,3]]) #-----> why wont this work?
print(two_dim_array[:2,[2,3]])   #-----> why would this work?
3
  • 1
    Slices and lists index in different ways. Do spend time reading the numpy indexing docs. It will save time later. Commented Feb 26, 2021 at 18:45
  • Its the difference in advance and basic indexing, you can find details here. I have tried to demonstrate the difference. Commented Feb 26, 2021 at 19:08
  • 1
    When the index contains 2 or more arrays (or lists that can be made into arrays), their interaction is defined by broadcasting. In your example you have shape (2,) and (2,) arrays resulting in a (2,) selection. The first needs to be (1,2) shaped if you want a (2,2) result. Commented Feb 26, 2021 at 20:31

1 Answer 1

2

Basic vs Advance indexing

To understand this behavior, you may want to understand how basic indexing and advance indexing works in numpy.

Basic indexing results in views, while advance indexing results in a copy.

Advance indexing can be combined with basic indexing but the way they behave is completely different. Basic indexing occurs when the object used for indexing is -

  • A slice object that is of the form start:stop:step
  • An integer
  • Or a tuple of slice objects and integers

Advance indexing is triggered when -

  • An ndarray of type integer or Boolean
  • A tuple with at least one sequence object
  • Is a non tuple sequence object

How they work

If you are working for indexes for multiple axes, advanced indexes (with arrays/lists) always are broadcast and iterated as one, while basic indexing (with slices) acts like repeated application of slicing over the axes.

  1. This means that when using basic indexing as arr[slice(0,3), slice(3,5)], you are taking a view of the first rows and then the 3rd and 4th column of the array.

  2. But when using advance indexing as arr[[0,2],[3,4]], you are taking the (0,3) and then the (2,4) indexed over both axis at once using broadcasting.

In your case, you are mixing basic and advance indexing. Let's first define the indexing objects and then play with them a bit to understand what's happening -

import numpy as np

two_dim_array = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])

rows = [0,1]
cols = [2,3]
row_slice = slice(0,2) #same as 0:2, or :2

In the first case, let's use basic indexing on axis=0 and advance indexing on axis=1. Here the advance indexing for the 2 columns is performed first and then copies of the subspace rows are fetched through basic indexing.

two_dim_array[row_slice, cols]
array([[3, 4],
       [7, 8]])

In second case, lets use advance indexing on both axes. This fetches copies of the array by iterating over both the rows and cols arrays/lists at once.

two_dim_array[rows, cols]
array([3, 8])    #(0,2) and (1,3) elements

But, as I mentioned, these indexes are broadcasted. Therefore, if you want to achieve the same result from advance indexing as you are with basic indexing, you can use something like np.ix_

obj = np.ix_(rows, cols)
obj
(array([[0],
        [1]]),
 array([[2, 3]]))

This creates 2 arrays in such a way that when broadcasted, result in (0,2), (0,3), (1,2), (1,3) indexes.

two_dim_array[obj]
array([[3, 4],
       [7, 8]])

Hope that clarifies how this works!

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.