I have a Numpy array and a list of indices whose values I would like to increment by one. This list may contain repeated indices, and I would like the increment to scale with the number of repeats of each index. Without repeats, the command is simple:
a=np.zeros(6).astype('int')
b=[3,2,5]
a[b]+=1
With repeats, I’ve come up with the following method.
b=[3,2,5,2] # indices to increment by one each replicate bbins=np.bincount(b) b.sort() # sort b because bincount is sorted incr=bbins[np.nonzero(bbins)] # create increment array bu=np.unique(b) # sorted, unique indices (len(bu)=len(incr)) a[bu]+=incr
Is this the best way? Is there are risk involved with assuming that the np.bincount and np.unique operations would result in the same sorted order? Am I missing some simple Numpy operation to solve this?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
In numpy >= 1.8, you can also use the at method of the addition ‘universal function’ (‘ufunc’). As the docs note:
For addition ufunc, this method is equivalent to a[indices] += b, except that results are accumulated for elements that are indexed more than once.
So taking your example:
a = np.zeros(6).astype('int')
b = [3, 2, 5, 2]
…to then…
np.add.at(a, b, 1)
…will leave a as…
array([0, 0, 2, 1, 0, 1])
Method 2
After you do
bbins=np.bincount(b)
why not do:
a[:len(bbins)] += bbins
(Edited for further simplification.)
Method 3
If b is a small subrange of a, one can refine Alok’s answer like this:
import numpy as np a = np.zeros( 100000, int ) b = np.array( [99999, 99997, 99999] ) blo, bhi = b.min(), b.max() bbins = np.bincount( b - blo ) a[blo:bhi+1] += bbins print a[blo:bhi+1] # 1 0 2
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0