Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accumulate constant value in Numpy Array

I'm trying to sum +1 to some specific cells of a numpy array but I can't find any way without slow loops:

coords = np.array([[1,2],[1,2],[1,2],[0,0]])
X      = np.zeros((3,3))

for i,j in coords:
  X[i,j] +=1 

Resulting in:

X = [[ 1.  0.  0.]
     [ 0.  0.  3.]
     [ 0.  0.  0.]]

X[coords[:,0],coords[:,1] += 1 returns

X = [[ 1.  0.  0.]
     [ 0.  0.  1.]
     [ 0.  0.  0.]]

Any help?

like image 843
memecs Avatar asked Apr 26 '16 11:04

memecs


People also ask

How do I add a constant to a NumPy array?

Adding a constant to a NumPy array is as easy as adding two numbers. To add a constant to each and every element of an array, use addition arithmetic operator + . To addition operator, pass array and constant as operands as shown below. where a is input array and c is a constant.

Can you use += on NumPy array?

Numpy arrays are mutable objects that have clearly defined in place operations. If a and b are arrays of the same shape, a += b adds the two arrays together, using a as an output buffer.

How do you make an array cumulative in Python?

Python allows us to perform the cumulative sum of array elements using the cumsum() method from the NumPy library. The numpy. cumsum() method returns the cumulative sum of elements in a given input array over a specified axis.

What does .all do in NumPy?

all() in Python. The numpy. all() function tests whether all array elements along the mentioned axis evaluate to True.


2 Answers

numpy.at is exactly for those situations.

In [1]: np.add.at(X,tuple(coords.T),1)

In [2]: X
Out[2]: 
array([[ 1.,  0.,  0.],
       [ 0.,  0.,  3.],
       [ 0.,  0.,  0.]])
like image 50
B. M. Avatar answered Sep 18 '22 13:09

B. M.


You can use np.bincount, like so -

out_shape = (3,3) # Input param

# Get linear indices corresponding to coords with the output array shape.
# These form the IDs for accumulation in the next step.
ids = np.ravel_multi_index(coords.T,out_shape)

# Use bincount to get 1-weighted accumulations. Since bincount assumes 1D
# array, we need to do reshaping before and after for desired output.
out = np.bincount(ids,minlength=np.prod(out_shape)).reshape(out_shape)

If you are trying to assign values other than 1s, you can use the additional input argument to feed in weights to np.bincount.

Sample run -

In [2]: coords
Out[2]: 
array([[1, 2],
       [1, 2],
       [1, 2],
       [0, 0]])

In [3]: out_shape = (3,3) # Input param
   ...: ids = np.ravel_multi_index(coords.T,out_shape)
   ...: out = np.bincount(ids,minlength=np.prod(out_shape)).reshape(out_shape)
   ...: 

In [4]: out
Out[4]: 
array([[1, 0, 0],
       [0, 0, 3],
       [0, 0, 0]], dtype=int64)
like image 35
Divakar Avatar answered Sep 16 '22 13:09

Divakar