ufunc Methods
Reviewed & published by Brayan K
Every NumPy universal function carries extra methods — reduce, accumulate, outer, reduceat, and at — that reshape how the operation is applied across an array.
Part of the free NumPy course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll collapse arrays to a single value, build running totals, form outer products of every pair, reduce over custom slices, and scatter-add repeated indices in place — all from one operation.
What You'll Learn in This Lesson
- Collapsing an array with .reduce
- Running totals with .accumulate
- Every-pair combinations with .outer
- Reducing over slices with .reduceat
- Unbuffered scatter-add with .at
- Choosing an axis for reductions
1 reduce and accumulate
ufunc.reduce applies the operation across an array to collapse it to a single value: np.add.reduce sums, np.multiply.reduce multiplies, np.maximum.reduce finds the max. ufunc.accumulate keeps every intermediate result, so np.add.accumulate is a running total. Pass axis to reduce along rows or columns of a 2D array.
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(np.add.reduce(a)) # 15
print(np.multiply.reduce(a)) # 120
print(np.add.accumulate(a)) # [ 1 3 6 10 15]
print(np.maximum.reduce(a)) # 5
# Reduce along an axis of a 2D array
m = np.array([[1, 2, 3], [4, 5, 6]])
print(np.add.reduce(m, axis=0)) # [5 7 9] (down columns)
print(np.add.reduce(m, axis=1)) # [ 6 15] (across rows)
# ✅ Expected output:
# 15
# 120
# [ 1 3 6 10 15]
# 5
# [5 7 9]
# [ 6 15]2 outer: Every Pair
ufunc.outer(x, y) applies the operation to every pair of elements, producing a 2D grid of shape (len(x), len(y)). np.multiply.outer is the classic outer product; np.add.outer builds an addition table.
import numpy as np
x = np.array([1, 2, 3])
y = np.array([10, 20])
print(np.add.outer(x, y))
# [[11 21]
# [12 22]
# [13 23]]
print(np.multiply.outer(x, y))
# [[10 20]
# [20 40]
# [30 60]]
# ✅ Expected output:
# [[11 21]
# [12 22]
# [13 23]]
# [[10 20]
# [20 40]
# [30 60]]3 reduceat and at
ufunc.reduceat(a, indices) reduces over the slices defined by the index list — a fast way to sum segments of a flat array. ufunc.at(a, indices, value) performs an unbuffered, in-place update; unlike a[idx] += 1, it correctly applies every repeated index (a scatter-add).
import numpy as np
a = np.arange(8) # [0 1 2 3 4 5 6 7]
# Sum the slices [0:2], [2:5], [5:]
print(np.add.reduceat(a, [0, 2, 5])) # [ 1 9 18]
# Scatter-add: every repeated index counts
arr = np.array([0, 0, 0, 0, 0])
idx = np.array([0, 1, 1, 2, 2, 2])
np.add.at(arr, idx, 1)
print(arr) # [1 2 3 0 0]
# ✅ Expected output:
# [ 1 9 18]
# [1 2 3 0 0]If you had written arr[idx] += 1 instead, the duplicate indices would each add only once — exactly the bug np.add.at exists to prevent.
🎯 YOUR TURN: Fill in the Blanks
Replace each ___ so the program sums an array and then builds its running total.
import numpy as np
v = np.array([2, 4, 6, 8])
# Collapse to a single sum
print(np.add.___(v)) # fill in: reduce -> 20
# Keep every running total
print(np.add.___(v)) # fill in: accumulate -> [ 2 6 12 20]
# Expected output:
# 20
# [ 2 6 12 20]Expected output: 20 then [ 2 6 12 20]. (Answers: reduce, accumulate.)
⚠️ Common Errors & Quick Reference
❌ Using a[idx] += 1 with duplicate indices
Buffered fancy indexing only adds once per unique index, undercounting duplicates.
✅ Fix: use np.add.at(a, idx, 1) for a correct unbuffered scatter-add.
❌ Forgetting the axis on a 2D reduce
Without axis, reduce collapses the whole array to one number.
✅ Fix: pass axis=0 (down columns) or axis=1 (across rows) to keep the dimension you want.
| Task | Code |
|---|---|
| Collapse to one value | np.add.reduce(a) |
| Running total | np.add.accumulate(a) |
| Every-pair grid | np.multiply.outer(x, y) |
| Reduce over slices | np.add.reduceat(a, [0, 2, 5]) |
| Scatter-add in place | np.add.at(a, idx, 1) |
🎯 Mini Challenge: Price Table and Event Counts
Build a price-by-quantity table with multiply.outer, then count repeated event codes with add.at.
import numpy as np
prices = np.array([10, 20, 30])
qtys = np.array([1, 2, 3, 4])
# Cost for every price/quantity combination
print(np.multiply.outer(prices, qtys))
# [[ 10 20 30 40]
# [ 20 40 60 80]
# [ 30 60 90 120]]
# Count how many times each event code fired
counts = np.zeros(5, dtype=int)
events = np.array([0, 2, 2, 4, 4, 4])
np.add.at(counts, events, 1)
print(counts) # [1 0 2 0 3]
# ✅ Expected output:
# [[ 10 20 30 40]
# [ 20 40 60 80]
# [ 30 60 90 120]]
# [1 0 2 0 3]❓ Frequently Asked Questions
Lesson complete — ufunc methods unlocked!
You can now collapse arrays with reduce, build running totals with accumulate, form grids with outer, segment with reduceat, and scatter-add safely with add.at.
Practice quiz
What does np.add.reduce([1, 2, 3, 4, 5]) return?
- 15
- [1 3 6 10 15]
- 5
- 120
Answer: 15. reduce collapses the array to a single value: 1+2+3+4+5 = 15.
What does np.add.accumulate([1, 2, 3, 4, 5]) return?
- 15
- 5
- [1 3 6 10 15]
- 120
Answer: [1 3 6 10 15]. accumulate keeps every running total.
What does np.multiply.reduce([1, 2, 3, 4, 5]) return?
- 15
- 120
- [1 2 6 24 120]
- 5
Answer: 120. multiply.reduce gives the product 1*2*3*4*5 = 120.
What does ufunc.outer(x, y) produce?
- A single scalar
- A 1D array
- A 2D grid combining every pair
- The element-wise sum
Answer: A 2D grid combining every pair. outer applies the op to every pair, making a (len(x), len(y)) grid.
What shape does np.multiply.outer(x, y) have for len(x)=3, len(y)=2?
- (3, 2)
- (2, 3)
- (6,)
- (5,)
Answer: (3, 2). outer produces shape (len(x), len(y)) = (3, 2).
What does np.add.reduceat(np.arange(8), [0, 2, 5]) return?
- [0 2 5]
- [28]
- [7 6 7]
- [1 9 18]
Answer: [1 9 18]. It sums slices [0:2], [2:5], [5:] -> 1, 9, 18.
Why use np.add.at(arr, idx, 1) instead of arr[idx] += 1?
- It is shorter to type
- It is unbuffered, so it counts every repeated index
- It sorts the array
- It returns a new array
Answer: It is unbuffered, so it counts every repeated index. np.add.at is unbuffered and correctly applies duplicate indices.
What does np.add.reduce(m, axis=0) do on a 2D array?
- Sums everything to one number
- Sums across each row
- Transposes m
- Sums down each column
Answer: Sums down each column. axis=0 reduces down columns, summing each column.
Which ufunc method gives a running total?
- reduce
- outer
- at
- accumulate
Answer: accumulate. accumulate keeps every intermediate result, a running total.
np.add.reduce(a) gives the same result as which function?
- np.prod(a)
- np.sum(a)
- np.cumsum(a)
- np.max(a)
Answer: np.sum(a). np.sum is essentially a friendly wrapper around np.add.reduce.
Continue this course
- Previous: Memory Layout & Strides
- Next: Statistics (percentile, median, std) — Summaries, percentiles, correlation and covariance along an axis
- Quick reference: NumPy cheat sheet
Frequently asked questions
What are ufunc methods in NumPy?
Every NumPy universal function (ufunc) like np.add or np.multiply carries extra methods that change how it is applied: reduce collapses an array to a single value, accumulate keeps the running results, outer combines every pair from two arrays, reduceat reduces over arbitrary slices, and at performs unbuffered in-place updates. They let one operation power summing, cumulative products, outer products, and scatter-add without writing loops.
What is the difference between np.add.reduce and np.sum?
np.add.reduce(a) and np.sum(a) compute the same total — np.sum is essentially a friendly wrapper around np.add.reduce. The reduce form is more general because the same pattern works for any ufunc: np.multiply.reduce gives a product, np.maximum.reduce gives the maximum, np.logical_and.reduce gives an all-test. Reaching for the ufunc method is handy when you want that uniform interface across operations.
Why use np.add.at instead of plain indexed addition?
When an index appears more than once, arr[idx] += 1 only adds once per unique index because the fancy-indexed read-modify-write is buffered. np.add.at(arr, idx, 1) is unbuffered, so it applies every repeated index, correctly counting duplicates. It is the standard way to do a scatter-add or build a histogram of repeated indices in place.