keng
keng

Reputation: 81

Slicing arrays with lists

So, I create a numpy array:

a = np.arange(25).reshape(5,5)

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

A conventional slice a[1:3,1:3] returns

array([[ 6, 7], [11, 12]])

as does using a list in the second a[1:3,[1,2]]

array([[ 6, 7], [11, 12]])

However, a[[1,2],[1,2]] returns

array([ 6, 12])

Obviously I am not understanding something here. That said, slicing with a list might on occasion be very useful.

Cheers,

keng

Upvotes: 8

Views: 196

Answers (4)

Daweo
Daweo

Reputation: 36550

You observed effect of so-called Advanced Indexing. Let consider example from link:

import numpy as np
x = np.array([[1, 2], [3, 4], [5, 6]])
print(x)
[[1 2]
 [3 4]
 [5 6]]
print(x[[0, 1, 2], [0, 1, 0]])  # [1 4 5]

You might think about this as providing lists of (Cartesian) coordinates of grid, as

print(x[0,1])  # 1
print(x[1,1])  # 4
print(x[2,0])  # 5

Upvotes: 2

ferhatelmas
ferhatelmas

Reputation: 3978

It triggers advanced indexing so first slice is the row index, second is the column index. For each row, it selects the corresponding column.

a[[1,2], [1,2]] -> [a[1, 1], a[2, 2]] -> [6, 12]

Upvotes: 0

cmxu
cmxu

Reputation: 972

a[[1,2],[1,2]] is reading this as, I want a[1,1] and a[2,2]. There are a few ways around this and I likely don't even have the best ways but you could try

a[[1,1,2,2],[1,2,1,2]]

This will give you a flattened version of above

a[[1,2]][:,[1,2]]

This will give you the correct slice, it works be taking the rows [1,2] and then columns [1,2].

Upvotes: 0

inspectorG4dget
inspectorG4dget

Reputation: 113985

In the last case, the two individual lists are treated as separate indexing operations (this is really awkward wording so please bear with me).

Numpy sees two lists of two integers and decides that you are therefore asking for two values. The row index of each value comes from the first list, while the column index of each value comes from the second list. Therefore, you get a[1,1] and a[2,2]. The : notation not only expands to the list you've accurately deduced, but also tells numpy that you want all the rows/columns in that range.

If you provide manually curated list indices, they have to be of the same size, because the size of each/any list is the number of elements you'll get back. For example, if you wanted the elements in columns 1 and 2 of rows 1,2,3:

>>> a[1:4,[1,2]]
array([[ 6,  7],
       [11, 12],
       [16, 17]])

But

>>> a[[1,2,3],[1,2]]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,)

The former tells numpy that you want a range of rows and specific columns, while the latter says "get me the elements at (1,1), (2,2), and (3, hey! what the?! where's the other index?)"

Upvotes: 0

Related Questions