Discussion:
[Numpy-discussion] Views and Increments
Anakim Border
2016-08-08 13:11:17 UTC
Permalink
Dear List,

I'm experimenting with views and array indexing. I have written two code
blocks that I was expecting to produce the same result.
a = np.arange(10)
b = a[np.array([1,6,5])]
b += 1
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a = np.arange(10)
a[np.array([1,6,5])] += 1
a
array([0, 2, 2, 3, 4, 6, 7, 7, 8, 9])


I understand what is happening in the first case. In fact, the
documentation is quite clear on the subject:

For all cases of index arrays, what is returned is a copy of the original
data, not a view as one gets for slices.

What about the second case? There, I'm not keeping a reference to the
intermediate copy (b, in the first example). Still, I don't see why the
update (to the copy) is propagating to the original array. Is there any
implementation detail that I'm missing?

Best,
ab
Sebastian Berg
2016-08-08 13:21:15 UTC
Permalink
Post by Anakim Border
Dear List,
I'm experimenting with views and array indexing. I have written two
code blocks that I was expecting to produce the same result.
a = np.arange(10)
b = a[np.array([1,6,5])]
b += 1
a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
a = np.arange(10)
a[np.array([1,6,5])] += 1
a
array([0, 2, 2, 3, 4, 6, 7, 7, 8, 9])
I understand what is happening in the first case. In fact, the
For all cases of index arrays, what is returned is a copy of the
original data, not a view as one gets for slices.
What about the second case? There, I'm not keeping a reference to the
intermediate copy (b, in the first example). Still, I don't see why
the update (to the copy) is propagating to the original array. Is
there any implementation detail that I'm missing?
The second case translates to:

tmp = a[np.array([1,6,5])] + 1
a[np.array([1,6,5])] = tmp

this is done by python, without any interplay of numpy at all. Which is
different from `arr += 1`, which is specifically defined and translates
to `np.add(arr, 1, out=arr)`.

- Sebastian
Post by Anakim Border
Best,
  ab
_______________________________________________
NumPy-Discussion mailing list
https://mail.scipy.org/mailman/listinfo/numpy-discussion
Marten van Kerkwijk
2016-08-08 16:32:36 UTC
Permalink
Hi Anakim,

The difference is really in the code path that gets taken: in the first
case, you go through `a.__getitem__(np.array([1,6,5])`, in the second
through `a.__setitem__(...)`. The increments would not work if you added an
extra indexing to it, as in:
```
a[np.array([1,6,5])][:] += 1
```

​(which would do `a.__getitem__(...).__setitem__(slice(None))`)

Hope this clarifies it,

Marten
Stephan Hoyer
2016-08-08 20:08:46 UTC
Permalink
Post by Anakim Border
a = np.arange(10)
a[np.array([1,6,5])] += 1
a
array([0, 2, 2, 3, 4, 6, 7, 7, 8, 9])
I haven't checked, but a likely explanation is that Python itself
interprets a[b] += c as a[b] = a[b] + c.

Python has special methods for inplace assignment (__setitem__) and inplace
arithmetic (__iadd__) but no special methods for inplace arithmetic and
assignment at the same time, so this is really out of NumPy's control here.
Loading...