Numpy: views vs copy by slicing

The accepted answer by John Zwinck is actually false (I just figured this out the hard way!).
The problem in the question is a combination of doing “l-value indexing” with numpy’s fancy indexing.
The following doc explains exactly this case

https://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html

in the section “But fancy indexing does seem to return views sometimes, doesn’t it?”

Edit:

To summarize the above link:

Whether a view or a copy is created is determined by whether the indexing can be represented as a slice.

Exception: If one does “fancy indexing” then always a copy is created. Fancy indexing is something like a[[1,2]].

Exception to the exception: If one does l-value indexing (i.e. the indexing happens left of the = sign), then the rule for when a view or a copy are created doesn’t apply anymore (though see below for a further exception). The python interpreter will directly assign the values to the left hand side without creating a copy or a view.

To prove that a copy is created in both cases, you can do the operation in two steps:

>>> a = np.arange(12).reshape(3, 4)
>>> b = a[0:3:2, :][:, [0, 2]]
>>> b[:] = 100
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

and

>>> b = a[:, [0, 2]][0:3:2, :]
>>> b[:] = 0
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Just as an aside, the question by the original poster is the exact problem stated at the end of the scipy-cookbook link above. There is no solution given in the book. The tricky thing about the question is that there are two indexing operations done in a row.

Exception to the exception to the exception: If there are two indexing operations done in a row on the left hand side (as is the case in this question), the direct assignment in l-value indexing only works if the first indexing operation can be represented as a slice. Otherwise a copy has to be created even though it is l-value indexing.

Leave a Comment