Skip to content
Laviyx Learn

Try

Python for Data course menu

NumPy Aggregations, axis and Random Numbers

Summarise NumPy arrays with sum, mean, median, std, min, max and percentile, understand the axis argument for rows and columns, find positions with argmax, and generate reproducible random numbers with default_rng.

Beginner7 min readUpdated
On this page

Aggregations reduce many numbers to one: a total, an average, a maximum. NumPy has fast versions of all of them, and the axis argument lets you compute them per row or per column of a table.

Whole-array summaries#

Python
import numpy as np

orders = np.array([250, 120, 560, 90, 310, 75, 430])
print(orders.sum(), orders.mean(), np.median(orders))
print(orders.min(), orders.max(), orders.max() - orders.min())
print(orders.std().round(2))
print(np.percentile(orders, [25, 50, 75]))
print(orders.argmax(), orders.argmin())     # positions of the max and min
Output
1835 262.14285714285717 250.0
75 560 485
170.79
[105. 250. 370.]
2 5

The median (250) is lower than the mean (262.14…) because the big orders pull the mean up. Descriptive Statistics explains when to use which.

The axis argument#

For a 2D array, axis=0 collapses the rows (giving one result per column) and axis=1 collapses the columns (one result per row):

Python
import numpy as np

# rows: three shops; columns: Mon..Thu sales
sales = np.array([
    [12, 15, 11, 20],
    [ 8, 22, 17, 13],
    [19, 10, 14, 16],
])
print(sales.sum())            # everything
print(sales.sum(axis=0))      # per day (down each column)
print(sales.sum(axis=1))      # per shop (across each row)
print(sales.mean(axis=1).round(2))
print(sales.argmax(axis=1))   # best day for each shop
Output
177
[39 47 42 49]
[58 60 59]
[14.5  15.   14.75]
[3 1 0]

A way to remember: the axis you name is the one that disappears. The result of axis=0 on a (3, 4) array has shape (4,).

Cumulative and counting functions#

Python
import numpy as np

deposits = np.array([100, 50, 200, 75])
print(np.cumsum(deposits))                # running balance
print(np.diff(np.array([3, 7, 12, 20])))  # change between neighbours

colours = np.array(["red", "blue", "red", "green", "red"])
values, counts = np.unique(colours, return_counts=True)
print(values, counts)
Output
[100 150 350 425]
[4 5 8]
['blue' 'green' 'red'] [1 1 3]

Missing values: NaN#

NumPy uses np.nan (not a number) for missing floats. Any aggregation that touches it returns nan, so use the nan-aware versions:

Python
import numpy as np

ratings = np.array([4.5, np.nan, 3.0, 5.0])
print(ratings.mean())
print(np.nanmean(ratings), np.nansum(ratings), np.isnan(ratings).sum())
Output
nan
4.166666666666667 12.5 1

pandas handles missing data more conveniently; see Missing Values.

Random numbers you can reproduce#

Simulations, sampling and machine learning need random numbers. Create a generator with np.random.default_rng. Giving it a seed makes the "random" numbers the same every run, so your results are reproducible:

Python
import numpy as np

rng = np.random.default_rng(42)
print(rng.integers(1, 7, size=10))              # ten dice rolls (7 is excluded)
print(rng.random(3).round(3))                   # floats in [0, 1)
print(rng.normal(loc=170, scale=8, size=4).round(1))   # heights around 170 cm
print(rng.choice(["heads", "tails"], size=5))

rng2 = np.random.default_rng(42)
print(rng2.integers(1, 7, size=10))             # same seed, same numbers
Output
[1 5 4 3 3 6 1 5 2 1]
[0.976 0.761 0.786]
[169.9 163.2 177.  176.2]
['tails' 'tails' 'heads' 'tails' 'tails']
[1 5 4 3 3 6 1 5 2 1]

default_rng is the modern API. Older code uses np.random.seed(42) with functions like np.random.randint; it still works, but new code should use a generator.

Simulating with random numbers#

Estimate the probability that two dice add up to 7 by rolling 100,000 times:

Python
import numpy as np

rng = np.random.default_rng(0)
rolls = rng.integers(1, 7, size=(100_000, 2))
sevens = (rolls.sum(axis=1) == 7).mean()
print(round(sevens, 4), round(6 / 36, 4))
Output
0.1678 0.1667

The simulated value is close to the exact answer, 6/36. The mean of a boolean array is the fraction of True values, a handy trick.

Common mistakes#

Practice#

Practice exercise

Monthly revenue (in thousands) for two products over six months is [[12, 15, 14, 18, 21, 19], [9, 8, 11, 10, 12, 15]]. Print each product's total and average (rounded to 1 decimal), the month number (1–6) with the highest combined revenue, and the month-to-month change in combined revenue.

Show hint

sum(axis=1) and mean(axis=1) per product; sum(axis=0) gives combined revenue per month; argmax() + 1 turns a position into a month number; np.diff gives the changes.

Show solution
Python
import numpy as np

revenue = np.array([[12, 15, 14, 18, 21, 19], [9, 8, 11, 10, 12, 15]])
print(revenue.sum(axis=1), revenue.mean(axis=1).round(1))
combined = revenue.sum(axis=0)
print(combined, "best month:", combined.argmax() + 1)
print(np.diff(combined))
Output
[99 65] [16.5 10.8]
[21 23 25 28 33 34] best month: 6
[2 2 3 5 1]

Key takeaway#

Next: Reshaping and Combining Arrays.

Finished this lesson?