Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Views and copies confusion with NumPy arrays when combining index operations

>>> a = np.arange(12).reshape(3,4)

>>> a[0:3:2, :][:, [0,2]] = 100   ### the first time
>>> a  
array([[100, 1, 100, 3],
[ 4, 5, 6, 7],
[100, 9, 100, 11]])

>>> a[:, [0, 2]][0:3:2, :] = 0    ### second time
>>> a   
array([[100, 1, 100, 3],
       [ 4, 5, 6, 7],
       [100, 9, 100, 11]])

I am really confused about views and copies in python. The code above shows that the first time the given rows and columns in array a was changed to 100, which changed the original array a.

However, the second time the original array was not changed. Why is that?

like image 800
Bratt Swan Avatar asked Sep 05 '25 20:09

Bratt Swan


1 Answers

A lookup with [:, [0,2]] will return a copy because it's advanced indexing. However when you assign to a slice (e.g. array[whatever] = sth) it won't create the copy but assign to the specified items, even if it's advanced indexing.

So the first example works because the first slicing returns a view and then it uses assignment for the slice of the view.

However the second one "fails" because you assign to a slice of a copy (because the advanced indexing is done before the regular indexing).

The difference is mainly because another method is responsible for setting (__setitem__) to slices than for getting (__getitem__) these slices. To disassemble your statements:

a[0:3:2, :][:, [0,2]] = 100 

a.__getitem__((slice(0, 3, 2), slice(None))).__setitem__((slice(None), [0, 2]), 100)
|-------------- returns a view ------------|

while the second one would be:

a[:, [0,2]][0:3:2, :] = 0

a.__getitem__((slice(None), [0, 2])).__setitem__((slice(0, 3, 2), slice(None)), 0)
|--------- returns a copy ---------|
like image 178
MSeifert Avatar answered Sep 09 '25 00:09

MSeifert