Reductions and axes

sum, mean, min along axis, keepdims, and cumsum.

A reduction collapses an axis into a number: totals, means, running sums. axis=0 walks down rows (per column). axis=1 walks across columns (per row).

Goal

Sum a units grid by city and by product, keep a dummy axis with keepdims, and print a cumulative sum.

Whole array vs one axis

# Rows: Nairobi, Mombasa, Kisumu  ·  cols: A, B, C
units = np.array(
    [
        [12, 7, 2],
        [9, 6, 0],
        [3, 11, 1],
    ],
    dtype=float,
)
print("all cells:", units.sum())
print("per product (axis=0):", units.sum(axis=0))
print("per city (axis=1):", units.sum(axis=1))

Nairobi’s total is 21. Product A’s total is 24.

keepdims for shares

units = np.array(
    [
        [12, 7, 2],
        [9, 6, 0],
        [3, 11, 1],
    ],
    dtype=float,
)
totals = units.sum(axis=1, keepdims=True)
print("totals shape:", totals.shape)
print(totals)
print()
print("row shares:")
print(np.round(units / totals, 3))

Without keepdims, totals is (3,) and dividing a (3, 3) grid is a broadcast trap (it would align as a row). With keepdims you get (3, 1) — one total per city, stretched across products.

Mean, min, max

rain = np.array(
    [
        [50, 40, 80, 150],
        [20, 15, 30, 90],
        [70, 80, 120, 180],
    ],
    dtype=float,
)
print("city means:", rain.mean(axis=1))
print("wettest month per city:", rain.max(axis=1))
print("driest city per month:", rain.min(axis=0))

cumsum

month = np.array([50, 40, 80, 150], dtype=float)
print(np.cumsum(month))

Running total for Nairobi’s Jan–Apr rain: 50, 90, 170, 320.

Tip

When you will divide a grid by its row totals, always pass keepdims=True (or use [:, np.newaxis]).