When I use the indices once to change the values, it works. However, when I use the indices twice to change the values, nothing has changed. Why I can't use the indices twice to change the values?
import numpy as np
a = np.arange(100)
a[np.array([10,20,30,40,50])] = 1
print(a[np.array([10,20,30,40,50])])
# array([1, 1, 1, 1, 1]) which can be modified as 1
a = np.arange(100)
(a[np.array([10,20,30,40,50])])[np.array([1,2,3])] = 1
print((a[np.array([10,20,30,40,50])])[np.array([1,2,3])])
# array([20, 30, 40]) which can not be modified as 1
CodePudding user response:
This is a confusing question about views and copies in NumPy. I found this question [Numpy: views vs copy by slicing] is similar to this one and this doc [Views versus copies in NumPy] mentioned by @Maltimore may explain.
NumPy Fancy Indexing returns a copy of numpy array instead of a view.
However, when set values to numpy array using fancy indexing, what python interpreter does is calling __setitem__
function. Take the code as an example.
In this line:
a[np.array([10,20,30,40,50])] = 1
What python actually does is
a.__setitem__(np.array([10,20,30,40,50]), 1)
i.e. there is not need to create neither a view or a copy because the method can be evaluated inplace (i.e. no new object creation is involved).
Break this line into the following code:
# (a[np.array([10,20,30,40,50])])[np.array([1,2,3])] = 1
a_copy = a[np.array([10,20,30,40,50])]
a_copy[np.array([1,2,3])] = 1
print(a[np.array([10,20,30,40,50])])
# [10, 20, 30, 40, 50]
print(a_copy)
# [10, 1, 1, 1, 50]
As a result, this line modifies the value of the copy, so the original numpy array is unchanged.