I'm very puzzled by the following behaviour of NumPy when assigning elements to an array using an array as indices. Here is a minimal working example:
import numpy as np
i = np.arange(2,4)
a = np.arange(5)
a[:][i] = 0 # this modifies the a array
print(a)
b = np.arange(5)
b[i][:] = 0 # this does NOT modify the b array
print(b)
Why is the a array modified and not the b array? I suspect we are modifying a copy of the b array, but I'm not sure how to show this explicitly. For example, id(a) and id(a[:]) yield different results, yet a is modified.
a[:] is a view of a, while a and a[:] are different python objects, they share the same underlying memory for the numpy data:
a2 = a[:]
a2.base is a # True
id(a2), id(a2.base), id(a) # (127331129255728, 127331129258032, 127331129258032)
However, b[i] is a new array, independent from b. b and b[:] each use a different space in memory to store the numpy data:
b2 = b[i]
b2.base # None
There is no good reason why you would need to chain [:][i] or [i][:] in numpy. Just remove the useless [:]:
b[i] = 0
As explained in the documentation:
Views are created when elements can be addressed with offsets and strides in the original array. Hence, basic indexing always creates views. [...] Advanced indexing, on the other hand, always creates copies.
a[:] # view (basic indexing)
a[1:3] # view (basic indexing)
a[1:3][:] # view (basic indexing)
a[[2, 3]] # copy (advanced indexing)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With