2

I have an array y with indexes of values that must be incremented by one in another array x just like x[y] += 1, This is an example:

>>> x = np.zeros(5,dtype=np.int)
>>> y = np.array([1,4])
>>> x
array([0, 0, 0, 0, 0])
>>> x[y] += 1
>>> x
array([0, 1, 0, 0, 1])

So far so good, but then I've this problem:

>>> x
array([0, 1, 0, 0, 1])
>>> y = np.array([1,1])
>>> x
array([0, 1, 0, 0, 1])
>>> x[y] += 1
>>> x
array([0, 2, 0, 0, 1])

I was expecting x to be array([0, 3, 0, 0, 1]): x[1] should be incremented by one twice, but I got it with x[1] incremented just by one.

How can I did it? Why is that happening?

Alvaro Fuentes
  • 16,937
  • 4
  • 56
  • 68

2 Answers2

3

Do this:

>>> x=np.array([0, 0, 0, 0, 0])
>>> y=np.array([1,4])
>>> x+=np.bincount(y, minlength=x.size)
>>> x
array([0, 1, 0, 0, 1])
>>> y=np.array([1,1])
>>> x+=np.bincount(y, minlength=x.size)
>>> x
array([0, 3, 0, 0, 1])
>>> map(id, x[y])
[20481944, 20481944]

x[1,1] only references the same element, +1 therefore only act on one element.

CT Zhu
  • 52,648
  • 17
  • 120
  • 133
2
x[y] += 1

is the equivalent to

x[y] = x[y] + 1
x[y]+1
# array([2, 2])

Effectively numpy operates on the terms in parallel, not sequentially.

x[y]=[4,3]  # or
x[y] += [4,3]

suggests that if different values are assigned to the same term, it is the last action that one has effect (but that probably isn't guaranteed).


np.add.at(x,y,1)

does what you expect.

from the documentation for np.add.at:

For addition ufunc, this method is equivalent to a[indices] += b, except that results are accumulated for elements that are indexed more than once. For example, a[[0,0]] += 1 will only increment the first element once because of buffering, whereas add.at(a, [0,0], 1) will increment the first element twice.

hpaulj
  • 221,503
  • 14
  • 230
  • 353