Universal functions & aggregation along axes
A universal function (ufunc) is a NumPy function that works element by element on whole arrays in compiled code.
np.add, np.sqrt, np.exp, np.maximum and the operators + - * / ** are all ufuncs. Combined with the axis
argument, they let you summarise data without a single Python loop.
Element-wise ufuncs
import numpy as np
prices = np.array([120.0, 450.0, 80.0, 999.0])
with_gst = np.round(prices * 1.18, 2) # 18% GST
log_p = np.log(prices) # natural log
capped = np.minimum(prices, 500) # cap each value at 500
floor_ceiling = np.clip(prices, 100, 800) # keep within [100, 800]
| Category | Examples |
|---|---|
| Arithmetic | np.add, np.subtract, np.multiply, np.divide, np.power |
| Maths | np.sqrt, np.exp, np.log, np.log1p, np.abs |
| Comparison | np.greater, np.equal, np.maximum, np.minimum |
| Rounding | np.round, np.floor, np.ceil |
Understanding axis
For a 2-D array, axis=0 collapses the rows (giving one result per column) and axis=1 collapses the
columns (giving one result per row).
# rows = 3 stores, columns = 4 quarters (₹ lakh)
sales = np.array([[12, 15, 11, 20],
[ 9, 10, 14, 13],
[18, 17, 16, 25]])
sales.sum(axis=0) # per quarter: [39 42 41 58]
sales.sum(axis=1) # per store: [58 46 76]
sales.max(axis=1) # best quarter value for each store
sales.argmax(axis=1) # index of best quarter: [3 2 3]
sales.mean() # overall mean (no axis)
A memory aid: the axis you pass is the axis that disappears from the shape. (3, 4) summed over axis 0
becomes (4,).
keepdims for broadcasting
To divide each store's quarters by that store's total, keep the reduced axis so the shapes line up:
share = sales / sales.sum(axis=1, keepdims=True) # (3, 4) / (3, 1)
print(share.round(2))
Without keepdims=True, the totals would have shape (3,), which broadcasts against columns and gives a wrong
answer or a shape error.
reduce and accumulate
Every binary ufunc has methods for reductions:
np.add.reduce([1, 2, 3, 4]) # 10, same as sum
np.add.accumulate([1, 2, 3, 4]) # [1 3 6 10], same as cumsum
np.maximum.accumulate([3, 1, 4, 2]) # running maximum: [3 3 4 4]
A running maximum is useful for "best sales so far" or drawdown calculations on stock prices.
Handling missing values
np.sum of an array containing np.nan returns nan. Use the nan-aware versions: np.nansum, np.nanmean,
np.nanmax, np.nanstd.
Common mistakes
- Mixing up axis 0 and axis 1; check the output shape every time.
- Forgetting
keepdims=Truewhen normalising rows. - Using Python's built-in
sum()ormax()on large arrays, which is far slower than the NumPy method. - Getting
nanresults because one missing value slipped in.
Practice
Build a 5 x 12 array of monthly sales for five branches. Find each branch's best month (index), each month's total, every branch's share of its annual sales per month (rows should sum to 1), and each branch's cumulative sales through the year.