zhenghao li
zhenghao li

Reputation: 57

python indexing don't change the numpy array

import numpy as np
a = np.array([[0, 1, 2],
              [0, 1, 2],
              [1, 1, 2]])

a[[0, 1]] = 100  # Changed
print(a)
a[[0, 1]][0, 0] = 98  # Not Changed
print(a)
a[0:2][0, 0] = 99  # Changed
print(a)

the output is :

# first
[[100 100 100]
[100 100 100]
[  1   1   2]]

# second
[[100 100 100]
[100 100 100]
[  1   1   2]]

# third
[[ 99 100 100]
[100 100 100]
[  1   1   2]]

so why the second way didn't change the a array, and the first way and third way worked? I had googled many answers,but I still not understand.

Upvotes: 3

Views: 56

Answers (1)

Dion
Dion

Reputation: 1552

It's complicated.

Basically, you are doing advanced indexing in case 1 and 2, and basic indexing in case 3. The NumPy docs on advanced indexing state:

Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).

So we already know the difference between case 2 and 3. Case 2 is basically equivalent to

b = a[[0, 1]]
b[0, 0] = 98

Since advanced indexing creates a copy, b is not linked to a anymore, and changes are not reflected. In case 3, we have

b = a[0:2]
b[0, 0] = 99

where b is now a view into a (basic indexing), so changes in b are reflected in a.

So what is going on in case 1?

The essential difference is that you cannot split this up into an assignment b = ... and subsequent setitem operation. Instead, you are doing setitem directly on the result on the indexing, which does not create a copy (only getitem operates on copies). So we get the same behavior as in case 2.

The following illustrates this:

Case 1 is equivalent to

setitem(a, [0, 1], 100)  # operates directly on a

Case 2 is equivalent to

setitem(
    getitem(a, [0, 1]),  # this is a copy
    [0, 0],
    98
)

Upvotes: 6

Related Questions