The axis Parameter Explained

Reviewed & published by Brayan K

The axis parameter tells a NumPy function which dimension to operate along and collapse — axis=0 works down the rows to give a result per column, while axis=1 works across the columns to give a result per row.

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 build a reliable mental model using sum and mean on 2D arrays, learn the one rule that ends the confusion forever, and see how keepdims keeps shapes broadcast-friendly.

What You'll Learn in This Lesson

1 The One Rule: The Named Axis Disappears

Forget "rows" and "columns" for a moment. The reliable rule is: the axis you pass is the one that gets collapsed and removed from the result's shape. A (3, 4) array reduced along axis=0 loses the 3 and becomes shape (4,); reduced along axis=1 it loses the 4 and becomes shape (3,).

import numpy as np

a = np.arange(12).reshape(3, 4)   # shape (3, 4)

a.sum(axis=0).shape   # (4,)  -> the 3 collapsed
a.sum(axis=1).shape   # (3,)  -> the 4 collapsed
import numpy as np

a = np.array([[1, 2, 3],
              [4, 5, 6]])         # shape (2, 3)

# axis=0 -> collapse the 2 rows -> one total per column
print(a.sum(axis=0))             # [5 7 9]
print(a.sum(axis=0).shape)       # (3,)

# axis=1 -> collapse the 3 columns -> one total per row
print(a.sum(axis=1))             # [ 6 15]
print(a.sum(axis=1).shape)       # (2,)

# ✅ Expected output:
# [5 7 9]
# (3,)
# [ 6 15]
# (2,)

2 axis=0 vs axis=1 in Practice

The same idea works for every reduction — mean, max, min, std, and more. Think of a small grades table where rows are students and columns are subjects: axis=0 gives the class average per subject, while axis=1 gives each student's average across subjects.

grades = np.array([[80, 90, 100],
                   [60, 70, 80]])
# rows = students, columns = subjects

grades.mean(axis=0)   # per-subject average: [70. 80. 90.]
grades.mean(axis=1)   # per-student average: [90. 70.]
import numpy as np

grades = np.array([[80, 90, 100],
                   [60, 70,  80]])

# Per-subject average (collapse students)
print(grades.mean(axis=0))       # [70. 80. 90.]

# Per-student average (collapse subjects)
print(grades.mean(axis=1))       # [90. 70.]

# Highest score in each subject
print(grades.max(axis=0))        # [ 80  90 100]

# ✅ Expected output:
# [70. 80. 90.]
# [90. 70.]
# [ 80  90 100]

3 keepdims=True for Broadcast-Friendly Shapes

Normally a reduction removes the axis entirely, dropping a dimension. Passing keepdims=True keeps that axis with size 1, so the result lines up perfectly for broadcasting back onto the original array — the standard way to subtract per-row or per-column means.

a = np.arange(12).reshape(3, 4)

a.sum(axis=1).shape                  # (3,)   -> dimension dropped
a.sum(axis=1, keepdims=True).shape   # (3, 1) -> dimension kept

# (3, 1) broadcasts cleanly against (3, 4):
a - a.mean(axis=1, keepdims=True)
import numpy as np

a = np.array([[1.0, 2.0, 3.0],
              [4.0, 5.0, 6.0]])        # shape (2, 3)

row_means = a.mean(axis=1, keepdims=True)
print(row_means.shape)               # (2, 1)
print(row_means)
# [[2.]
#  [5.]]

# Subtract each row's mean from that row (broadcasting)
print(a - row_means)
# [[-1.  0.  1.]
#  [-1.  0.  1.]]

# ✅ Expected output:
# (2, 1)
# [[2.]
#  [5.]]
# [[-1.  0.  1.]
#  [-1.  0.  1.]]

🎯 YOUR TURN: Fill in the Blank

Replace ___ with the correct axis number so you get one total per column.

import numpy as np

sales = np.array([[10, 20, 30],
                  [40, 50, 60]])      # rows = days, cols = products

# 🎯 YOUR TURN:
# Get the TOTAL sales for each PRODUCT (one number per column).
# Hint: to get a result per column, collapse the rows.
totals = sales.sum(axis=___)

print(totals)
# Expected output:
# [50 70 90]

Answer: 0 — collapsing axis 0 (the rows) leaves one total per column.

! Common Errors (And How to Fix Them)

❌ Reading axis=0 as "sum the rows"

It collapses the row dimension, giving a per-column result:

# a = [[1, 2], [3, 4]]
a.sum(axis=0)   # [4 6]  (per column), NOT [3, 7]

✅ Fix: say "the named axis disappears" — axis=0 leaves a result per column.

❌ "operands could not be broadcast" after a reduction

a - a.mean(axis=1)   # ❌ (3,4) vs (3,) shapes clash

✅ Fix: add keepdims=True so the result is (3, 1) and broadcasts.

❌ "axis 2 is out of bounds"

A 2D array only has axes 0 and 1.

✅ Fix: check arr.ndim; valid axes run from 0 to ndim − 1.

🎯 Mini Challenge: Summarize a Table

Given a temperatures table (rows = cities, columns = days), find the warmest day overall per city and the average temperature per day across cities.

import numpy as np

temps = np.array([[15, 18, 21],     # city A
                  [10, 12, 14],     # city B
                  [20, 22, 19]])    # city C

# Warmest day for each city (collapse the days -> per row)
print(temps.max(axis=1))            # [21 14 22]

# Average temperature each day across cities (collapse cities -> per column)
print(temps.mean(axis=0))           # [15. 17.33333333 18.]

# Grand average over everything (no axis)
print(round(temps.mean(), 2))       # 16.78

# ✅ Expected output:
# [21 14 22]
# [15.         17.33333333 18.        ]
# 16.78

❓ Frequently Asked Questions

Lesson complete — axis confusion solved!

You now know that the axis you name is the one that collapses: axis=0 gives per-column results, axis=1 gives per-row results, and keepdims=True keeps shapes broadcast-ready.

Practice quiz

What is the one reliable rule about the axis you pass to a reduction?

  • It is the axis you keep
  • It is always the rows
  • It is the axis that gets collapsed and removed
  • It must be 1 for 2D arrays

Answer: It is the axis that gets collapsed and removed. The named axis disappears from the result's shape.

A (3, 4) array reduced along axis=0 becomes which shape?

  • (3,)
  • (4,)
  • (3, 4)
  • (1, 4)

Answer: (4,). axis=0 loses the 3, leaving shape (4,).

A (3, 4) array reduced along axis=1 becomes which shape?

  • (3,)
  • (4,)
  • (3, 4)
  • (1, 3)

Answer: (3,). axis=1 loses the 4, leaving shape (3,).

For grades = [[80,90,100],[60,70,80]], what is grades.mean(axis=0)?

  • [90. 70.]
  • 75.
  • [80. 90. 100.]
  • [70. 80. 90.]

Answer: [70. 80. 90.]. axis=0 collapses the students, giving the per-subject averages [70. 80. 90.].

For grades = [[80,90,100],[60,70,80]], what is grades.mean(axis=1)?

  • [70. 80. 90.]
  • [90. 70.]
  • 80.
  • [80. 60.]

Answer: [90. 70.]. axis=1 collapses the subjects, giving each student's average: 90 and 70.

What does keepdims=True do during a reduction?

  • Doubles the result
  • Removes one extra axis
  • Keeps the reduced axis with size 1
  • Returns a scalar

Answer: Keeps the reduced axis with size 1. keepdims=True keeps the collapsed axis as size 1 for easy broadcasting.

For grades = [[80,90,100],[60,70,80]], what is grades.max(axis=0)?

  • [80 90 100]
  • 100
  • [100 80]
  • [90 70]

Answer: [80 90 100]. axis=0 collapses rows, giving the highest score in each subject column.

Which call returns a single scalar over the entire array?

  • arr.sum(axis=0)
  • arr.sum(axis=1)
  • arr.sum(keepdims=True)
  • arr.sum()

Answer: arr.sum(). With no axis, the reduction runs over the whole flattened array.

A (3, 4) array reduced along axis=1 with keepdims=True becomes which shape?

  • (3,)
  • (3, 1)
  • (1, 4)
  • (4,)

Answer: (3, 1). keepdims keeps the collapsed axis at size 1, giving (3, 1).

Reading axis=0 as 'sum the rows you see' is wrong because...

  • axis=0 errors on 2D arrays
  • it sums diagonals
  • it actually gives a per-column result
  • it returns a scalar

Answer: it actually gives a per-column result. axis=0 collapses the row dimension, producing one value per column.

Continue this course

Frequently asked questions

What does axis=0 mean versus axis=1?

axis=0 runs DOWN the rows, collapsing the row dimension so you get one result per column. axis=1 runs ACROSS the columns, collapsing the column dimension so you get one result per row. The simplest rule: the axis you name is the one that disappears from the result's shape.

Why do my axis results come out with the wrong orientation?

It is almost always a mix-up between 'the axis you reduce over' and 'the axis you keep'. sum(axis=0) does NOT mean 'sum the rows' — it means 'collapse axis 0', which produces a per-column total. Picture the dimension being squashed flat: whatever index you pass is the one that is removed.

What does keepdims=True do?

Normally a reduction removes the axis you operate on, lowering the number of dimensions. keepdims=True keeps that axis with size 1 instead, so a (3, 4) array reduced along axis=1 becomes (3, 1) rather than (3,). That shape is perfect for broadcasting the result back against the original array, for example to subtract per-row means.

If I do not pass axis at all, what happens?

Without an axis argument, the reduction is applied over the entire flattened array, returning a single scalar. arr.sum() adds every element regardless of shape. Pass axis only when you want a result per row or per column instead of one grand total.