np.add.at() Function in NumPy

Recently, I was working on a project that required me to add values to specific indices of a NumPy array without creating a new array. The challenge was to update values in-place, especially when dealing with duplicate indices. That’s when I discovered the np.add.at() function in NumPy is very useful.

In this article, I’ll cover everything you need to know about using np.add.at() in Python, from basic usage to practical applications in data science and machine learning.

np.add.at() and Why Use It?

The np.add.at() function allows you to add values to specific positions in a NumPy array without creating a new copy. This function is especially valuable when:

  1. You need to add values to an array at specific indices
  2. You have duplicate indices where you want additions to accumulate
  3. You’re working with large datasets and want to avoid creating temporary arrays

Think of it as a more efficient alternative to using a loop or array slicing when you need to update specific positions in your array.

Read np.round() Function in Python

Basic Syntax of np.add.at()

The basic syntax of the np.add.at() function is:

np.add.at(a, indices, values)

Where:

  • a is the target array you want to modify
  • indices specifies the locations where values should be added
  • values contains the values to add at the specified indices

Let me show you how this works with a simple example:

import numpy as np

# Create a sample array
arr = np.zeros(10)

# Add values at specific indices
indices = [1, 4, 7]
values = [10, 20, 30]

np.add.at(arr, indices, values)
print(arr)

Output:

[ 0. 10.  0.  0. 20.  0.  0. 30.  0.  0.]

I executed the above example code and added the screenshot below.

np add at

np.add.at() is useful for performing unbuffered, in-place additions at specific indices in an array.

Read Check if NumPy Array is Empty in Python

Handle Duplicate Indices

One of the most efficient features of np.add.at() is how it handles duplicate indices. Unlike standard NumPy indexing, which can only assign the last value, np.add.at() accumulates values at duplicate indices.

Here’s an example that demonstrates this:

import numpy as np

# Create a sample array
arr = np.zeros(5)

# Add values at indices, with duplicates
indices = [0, 2, 2, 3, 3, 3]
values = [5, 10, 15, 20, 25, 30]

np.add.at(arr, indices, values)
print(arr)

Output:

[ 5.  0. 25. 75.  0.]

I executed the above example code and added the screenshot below.

np.add.at

Notice how the value at index 2 is 25 (10+15) and the value at index 3 is 75 (20+25+30). This is what makes np.add.at() particularly useful for histogram creation, counting occurrences, and many machine learning algorithms.

Check out NumPy Sum of Squares in Python

Advanced Usage with Multi-dimensional Arrays

The np.add.at() function also works with multi-dimensional arrays in Python. For multi-dimensional arrays, the indices need to be specified for each dimension.

import numpy as np

# Create a 3x3 array
arr = np.zeros((3, 3))

# Define indices for both dimensions
rows = [0, 1, 2, 0]
cols = [0, 1, 2, 0]

# Values to add
values = [5, 10, 15, 20]

np.add.at(arr, (rows, cols), values)
print(arr)

Output:

[[25.  0.  0.]
 [ 0. 10.  0.]
 [ 0.  0. 15.]]

I executed the above example code and added the screenshot below.

numpy add at

Notice that the value at position (0,0) is 25 (5+20) because we’re adding to this position twice.

Practical Applications of np.add.at()

Let me show you some practical applications of np.add.st()

1. Create Histograms

One of the most common uses of np.add.at() is for efficiently creating histograms:

import numpy as np
import matplotlib.pyplot as plt

# Generate random data
data = np.random.randint(0, 10, size=1000)

# Create histogram using np.add.at()
histogram = np.zeros(10)
np.add.at(histogram, data, 1)

# Plot the histogram
plt.bar(range(10), histogram)
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.title('Histogram using np.add.at()')
plt.show()

np.add.at() lets you efficiently build histograms by accumulating values directly at specific indices. This avoids manual counting and is ideal for fast, large-scale data.

Read NumPy Concatenate vs Append in Python

2. Feature Engineering in Machine Learning

When working with sparse features in machine learning, np.add.at() can be used to efficiently accumulate feature values:

import numpy as np

# Imagine we have feature indices and their values
feature_indices = [0, 2, 1, 0, 3, 2]
feature_values = [0.5, 0.3, 0.7, 0.2, 0.9, 0.4]

# Create feature vector
feature_vector = np.zeros(4)
np.add.at(feature_vector, feature_indices, feature_values)

print(feature_vector)
# Output: [0.7 0.7 0.7 0.9]

When handling sparse or repeated features, np.add.at() ensures accurate accumulation of values at the same indices. It helps build feature vectors without conflict or overwriting.

3. Efficient Graph Operations

When working with graph algorithms, we often need to update node or edge weights:

import numpy as np

# Imagine we have a graph with edges represented as pairs of nodes
edges = [(0, 1), (1, 2), (2, 0), (1, 0)]
weights = [3, 7, 2, 5]

# Initialize node strengths
node_strengths = np.zeros(3)

# For each edge, add its weight to both connected nodes
from_nodes, to_nodes = zip(*edges)
np.add.at(node_strengths, from_nodes, weights)
np.add.at(node_strengths, to_nodes, weights)

print(node_strengths)
# Output: [10. 15. 9.]

In graph processing, np.add.at() simplifies updating node weights from multiple edges. It handles repeated indices correctly, making algorithms both cleaner and more reliable.

Check out NumPy Linspace in Python

Performance Comparison

One of the main advantages of np.add.at() is its performance, especially when dealing with large arrays or many updates. Let’s compare it with a few alternatives:

import numpy as np
import time

size = 1000000
updates = 100000

# Create arrays
arr1 = np.zeros(size)
arr2 = np.zeros(size)
arr3 = np.zeros(size)

indices = np.random.randint(0, size, updates)
values = np.random.random(updates)

# Method 1: Using a loop
start = time.time()
for i, val in zip(indices, values):
    arr1[i] += val
print(f"Loop time: {time.time() - start:.5f} seconds")

# Method 2: Using np.add.at()
start = time.time()
np.add.at(arr2, indices, values)
print(f"np.add.at() time: {time.time() - start:.5f} seconds")

# Method 3: Using np.bincount for simple cases
start = time.time()
if len(arr3.shape) == 1:  # Only works for 1D arrays
    arr3 += np.bincount(indices, weights=values, minlength=size)
print(f"np.bincount time: {time.time() - start:.5f} seconds")

# Verify all methods give the same result
print(f"Methods produce same result: {np.allclose(arr1, arr2) and np.allclose(arr1, arr3)}")

In most cases, np.add.at() is significantly faster than using loops, especially when the number of updates is large compared to the array size.

Common Mistakes and How to Avoid Them

Now I will explain to you some mistakes that can happen while working with np.add.at() function and how to avoid it.

Read NumPy Read CSV with Header in Python

Mistake 1: Forgetting that np.add.at() Modifies the Array In-place

Unlike many NumPy functions that return a new array, np.add.at() modifies the Python array in-place:

import numpy as np

arr = np.zeros(5)
# This doesn't assign the result to anything
result = np.add.at(arr, [0, 2], [10, 20])
print(result)  # Output: None
print(arr)     # Output: [10.  0. 20.  0.  0.]

Always remember that np.add.at() updates the original array directly and returns None.

Mistake 2: Using Incompatible Indices and Values Shapes

Make sure your indices and values have compatible shapes:

import numpy as np

arr = np.zeros(5)

# This will work
indices = [0, 2, 3]
values = [10, 20, 30]
np.add.at(arr, indices, values)

# Reset array
arr = np.zeros(5)

# This will raise an error - different shapes
indices = [0, 2, 3]
values = [10, 20]  # One fewer value than index
try:
    np.add.at(arr, indices, values)
except Exception as e:
    print(f"Error: {e}")

Ensure that your indices and values have matching shapes to avoid shape-mismatch errors.

Mistake 3: Out-of-bounds Indices

Be careful with indices that exceed the size of your array:

import numpy as np

arr = np.zeros(5)

# This will raise an error
indices = [0, 5, 3]  # Index 5 is out of bounds for arr
values = [10, 20, 30]
try:
    np.add.at(arr, indices, values)
except Exception as e:
    print(f"Error: {e}")

Avoid using indices that exceed the array size, as it will raise an IndexError.

I hope you found this article helpful. The np.add.at() function might seem like a small utility, but it can significantly simplify your code and improve performance when dealing with array updates at specific indices.

Whether you’re working on data science projects, machine learning algorithms, or simply need an efficient way to update arrays with accumulation, np.add.at() is a tool worth adding to your NumPy arsenal.

Related tutorials you may like:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.