13

I have an array:

A = np.array([0, 0, 0])

and list of indices with repetitions:

idx = [0, 0, 1, 1, 2, 2]

and another array i would like to add to A using indices above:

B = np.array([1, 1, 1, 1, 1, 1])

The operation:

A[idx] += B

Gives the result: array([1, 1, 1]), so obviously values from B were not summed up. What is the best way to get as a result array([2, 2, 2])? Do I have to iterate over indices?

Alex Riley
  • 169,130
  • 45
  • 262
  • 238
mrkwjc
  • 1,080
  • 8
  • 17
  • 1
    related: http://stackoverflow.com/q/15973827/2096752 and http://stackoverflow.com/q/16034672/2096752 – shx2 Jun 07 '14 at 16:46
  • 1
    The first duplicate is not actually a duplicate, it talks about assignment which is completely different from addition. – LucasB Jan 15 '17 at 11:36
  • 1
    I feel also the second duplicate is not an exact duplicate. Please remove this duplication info. – mrkwjc Dec 06 '19 at 08:35

2 Answers2

30

for this numpy 1.8 added the at reduction:

at(a, indices, b=None)

Performs unbuffered in place operation on operand 'a' for elements specified by 'indices'. 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.

.. versionadded:: 1.8.0

In [1]: A = np.array([0, 0, 0])
In [2]: B = np.array([1, 1, 1, 1, 1, 1])
In [3]: idx = [0, 0, 1, 1, 2, 2]
In [4]: np.add.at(A, idx, B)
In [5]: A
Out[5]: array([2, 2, 2])
jtaylor
  • 2,389
  • 19
  • 19
  • 1
    That's it! It seems to be couple of times faster than iterating and works also on multidimensional arrays. Thanks. – mrkwjc Jun 08 '14 at 06:43
1

How about:

A = np.array([1, 2, 3])
idx = [0, 0, 1, 1, 2, 2]
A += np.bincount(idx, minlength=len(A))

Obviously it's even more simple if A starts off as zeros:

A = np.bincount(idx)
Bi Rico
  • 25,283
  • 3
  • 52
  • 75