Understanding Axes
What axis 0, axis 1 and axis 2 mean, how sum(axis=…) collapses a dimension, and how to predict the result shape — with ASCII diagrams.
"Total runs per player" and "total runs per match" use the same data and the same function — sum — the only difference is the axis. The axis parameter is one of the most confusing parts of NumPy for beginners, so let's anchor it properly.
Definition
An axis is one dimension of an array, numbered from
0in the same order as the shape tuple. When you passaxis=kto a reduction function such assum,mean,maxormin, NumPy collapses (reduces) that dimension: it combines all values along axis k into one value, and the result's shape is the original shape with entry k removed.
- Axis number = position in the shape. For shape
(3, 14): axis 0 has length 3 (players), axis 1 has length 14 (matches). - Reduction — a function that turns many values into one (sum, mean, max, min, std …).
- Collapse — the chosen axis disappears from the result's shape.
- No axis (
axis=None, the default) — reduce everything to a single number.
Syntax
python
arr.sum(axis=None, keepdims=False)
np.sum(arr, axis=None, keepdims=False)
# same 'axis' parameter in: mean, max, min, std, var, prod, argmax, argmin, cumsum ...| Parameter | Meaning | Default |
|---|---|---|
axis | Which axis to collapse: an int (0, 1, 2, or negative like -1 = last), a tuple of ints, or None | None (all elements) |
keepdims | If True, the collapsed axis is kept with length 1 (handy for broadcasting) | False |
Axes of a 2D array
text
team_scores.shape = (3, 14)
| |
axis 0 axis 1
(rows / (columns /
players) matches)
axis=0 -> collapse the ROWS: go DOWN each column -> one value per column, shape (14,)
[72, 45, 88, ...] <- Virat
[56, 0, 74, ...] <- Rohit
[45, 32, 0, ...] <- Hardik
| | |
v v v
[173, 77, 162, ...] <- per-match totals
axis=1 -> collapse the COLUMNS: go ACROSS each row -> one value per row, shape (3,)
[72, 45, 88, 31, ...] --> 779 (Virat total)
[56, 0, 74, 88, ...] --> 710 (Rohit total)
[45, 32, 0, 67, ...] --> 580 (Hardik total)Memory trick:
axis=kmakes dimension k disappear. axis=0 removes the first number of the shape (players gone → one value per match); axis=1 removes the second (matches gone → one value per player).
Example — sum(axis=…) on the team table
python
import numpy as np
team_scores = np.array([
[72, 45, 88, 31, 64, 0, 103, 52, 19, 77, 41, 93, 28, 66],
[56, 0, 74, 88, 32, 45, 61, 17, 90, 38, 72, 5, 83, 49],
[45, 32, 0, 67, 18, 54, 78, 22, 41, 33, 60, 15, 88, 27],
])
print(team_scores.sum(axis=1))
print(team_scores.sum(axis=0))
print(team_scores.sum())
print(team_scores.mean(axis=1).round(1))text
[779 710 580]
[173 77 162 186 114 99 242 91 150 148 173 113 199 142]
2069
[55.6 50.7 41.4]How it works:
axis=1→ per player totals (779, 710, 580): shape (3, 14) → (3,).axis=0→ per match totals (match 1: 72 + 56 + 45 = 173): shape (3, 14) → (14,).- No axis → grand total of all 42 scores: 2069.
mean(axis=1)→ each player's average.
Example — a small marks table, result shapes, and keepdims
python
import numpy as np
marks = np.array([
[80, 90, 70],
[60, 85, 95],
[75, 88, 92],
])
print(marks.sum(axis=0))
print(marks.sum(axis=1))
print(marks.sum())
print(marks.max(axis=0), marks.max(axis=1))
print(marks.sum(axis=0).shape, marks.sum(axis=1).shape)
print(marks.sum(axis=1, keepdims=True))
print(marks.sum(axis=1, keepdims=True).shape)
try:
marks.sum(axis=2)
except Exception as e:
print(type(e).__name__ + ":", e)text
[215 263 257]
[240 240 255]
735
[80 90 95] [90 95 92]
(3,) (3,)
[[240]
[240]
[255]]
(3, 1)
AxisError: axis 2 is out of bounds for array of dimension 2How it works: rows are students (Rahul, Aman, Munna), columns are subjects. axis=0 gives subject totals, axis=1 gives student totals. Both results have shape (3,) here only because the table is square — always reason from which axis disappears. keepdims=True keeps the collapsed axis as length 1, giving a column of shape (3, 1). A 2D array has only axes 0 and 1, so axis=2 raises an AxisError.
Axes of a 3D array
For two_seasons with shape (2, 3, 8) = (seasons, players, matches):
text
axis 0 = seasons (2) -> "across seasons": combine 2023 + 2024
axis 1 = players (3) -> "across players": combine Virat + Rohit + Hardik
axis 2 = matches (8) -> "across matches": combine M1 + M2 + ... + M8
sum(axis=0) -> shape (3, 8): each player's match-by-match total over both seasons
sum(axis=1) -> shape (2, 8): team total per match, for each season
sum(axis=2) -> shape (2, 3): each player's season totalpython
import numpy as np
two_seasons = np.array([
[[72, 45, 88, 31, 64, 0, 103, 52],
[56, 0, 74, 88, 32, 45, 61, 17],
[45, 32, 0, 67, 18, 54, 78, 22]],
[[65, 80, 44, 91, 33, 58, 22, 71],
[39, 55, 82, 0, 77, 21, 64, 48],
[28, 44, 63, 37, 82, 0, 55, 71]],
])
print("axis0:\n", two_seasons.sum(axis=0))
print("axis1:\n", two_seasons.sum(axis=1))
print("axis2:\n", two_seasons.sum(axis=2))
print(two_seasons.sum(axis=(0, 2)))
print(two_seasons.sum(axis=-1))text
axis0:
[[137 125 132 122 97 58 125 123]
[ 95 55 156 88 109 66 125 65]
[ 73 76 63 104 100 54 133 93]]
axis1:
[[173 77 162 186 114 99 242 91]
[132 179 189 128 192 79 141 190]]
axis2:
[[455 373 316]
[464 386 380]]
[919 759 696]
[[455 373 316]
[464 386 380]]How it works:
axis=0: seasons disappear → (3, 8). Virat's match 1 over both seasons = 72 + 65 = 137.axis=1: players disappear → (2, 8). Season 1, match 1 team total = 72 + 56 + 45 = 173.axis=2: matches disappear → (2, 3). Virat's 2023 season total = 455.axis=(0, 2): collapse seasons and matches → (3,): each player's career total (Virat 455 + 464 = 919).axis=-1means "the last axis" — identical toaxis=2here. Negative axes are handy when you don't care how many dimensions come before.
Quick reference
| Shape | axis=0 result | axis=1 result | axis=2 result | No axis |
|---|---|---|---|---|
(14,) | () — single number | error | error | single number |
(3, 14) | (14,) per match | (3,) per player | error | single number |
(2, 3, 8) | (3, 8) | (2, 8) | (2, 3) | single number |
Common mistakes
- ❌ "axis=0 means rows, so sum(axis=0) gives row totals." ✅ axis=0 collapses the rows, giving one value per column. Think "which dimension disappears?".
- ❌ Trusting the result shape on a square table to tell you which axis you used. ✅ Check with a recognisable value (e.g. Virat's total 779).
- ❌ Using
axis=2on a 2D array. ✅ Valid axes are0 … ndim-1(or-1 … -ndim). - ❌ Forgetting
keepdims=Truewhen you want to divide each row by its own total. ✅marks / marks.sum(axis=1, keepdims=True)— the (3, 1) column broadcasts correctly.
Interview tip
Q: For an array of shape (5, 4, 3), what is the shape of arr.mean(axis=1)?
A: (5, 3) — axis 1 (length 4) is collapsed and removed; the other dimensions stay in order.
Key points to remember
- An axis is one dimension of the array, numbered from 0 in shape order (axis 0 = first number of the shape).
- axis=k in sum/mean/max/min collapses dimension k: the result's shape is the original shape with entry k removed.
- For a (players, matches) table: axis=0 gives one value per match, axis=1 gives one value per player.
- With no axis (default None), the reduction runs over all elements and returns a single number.
- For 3D (seasons, players, matches): axis=0 → (players, matches), axis=1 → (seasons, matches), axis=2 → (seasons, players).
- axis can be negative (-1 = last axis) or a tuple to collapse several axes at once.
- keepdims=True keeps the collapsed axis with length 1, which is useful for broadcasting.
Try it yourself
Per player vs per match
Collapsing each axis of a 3D array
keepdims: each player's share of his runs
Practice: averages per player and per match
Revision Flashcards
Tap a card to flip it and see the answer.
