Array Maths and Broadcasting
Overview
Arrays of different shapes can still meet, under one clear rule.
What You Will Learn in This Lesson
By the end of this lesson, you will be able to:
- Combine two arrays of the same shape without a loop or a zip.
- State the broadcasting rule and apply it to a scalar and a row.
- Predict which pairs of shapes cannot be combined.
- Centre and scale a column in one expression.
Why This Matters
Broadcasting is why + 5 worked in the first lesson, and it is the reason a per-column adjustment does not need a loop. It is also the source of the shape errors that stop a script dead — and those errors are readable once you know the rule they are enforcing.
Step 1: Elementwise by default
Two arrays of the same shape combine position by position. No loop, no zip.
Same shape, straightforward
Every arithmetic operator works this way, and so do the comparisons you met in the last lesson.
import numpy as np
marks = np.array([45, 30, 50])
bonus = np.array([5, 10, 0])
print(marks + bonus)
print(marks * 2)
print(marks / 50)
The methods that reduce
Alongside the operators, an array carries its own summaries. Each collapses the array to one number, unless you say otherwise — which is the next lesson.
import numpy as np
marks = np.array([45, 30, 50])
print(marks.sum(), marks.mean(), marks.min(), marks.max())
print(round(marks.std(), 3))
Mini Practice #1: Weighted total
Try It YourselfTwo tests carry different weights. Multiply each column by its weight and total each student, in two expressions and no loop.
Step 2: Broadcasting stretches the smaller one
A single number is treated as if repeated to fit. That is why + 5 worked, and the same rule extends to whole rows and columns.
The rule
Line the shapes up from the right. Two dimensions are compatible if they are equal, or if one of them is 1. Anything else has no defined meaning and numpy says so rather than guessing.
import numpy as np
table = np.array([[1, 2, 3],
[4, 5, 6]]) # shape (2, 3)
per_column = np.array([10, 20, 30]) # shape (3,)
# (2, 3) and (3,) line up on the right: 3 == 3, and the missing
# dimension is treated as 1. The row is applied to every row.
print(table + per_column)
When it refuses
A shape mismatch is a real error, not a numpy quirk — there is no single sensible answer for adding three numbers to rows of four.
import numpy as np
try:
np.array([1, 2, 3]) + np.array([1, 2, 3, 4])
except ValueError as exc:
print("ValueError:", exc)
Centring, the everyday use
Subtracting the mean is broadcasting a single number across the whole array. Dividing by the standard deviation as well gives you a standardised column, which is the form most models want.
import numpy as np
values = np.array([2.0, 4.0, 6.0])
centred = values - values.mean()
print(centred)
print(centred / values.std())
Mini Practice #2: Read the shape error
Try It YourselfThis raises. Read the message, then change the second array so the shapes line up.
Step 3: When to Use It
Applying one value to everything
A scalar broadcasts across the whole array: offsets, scaling, unit conversions.
celsius = (fahrenheit - 32) * 5 / 9
A row or column against a table
Subtract a per-column mean from every row, where the shapes line up from the right.
When Not to Use It
Do not rely on broadcasting when you are not sure of the shapes. Print .shape first — a silent broadcast between the wrong axes gives a result of the wrong size, not an error.
End-of-Lesson Exercises
Exercise 1: Centre on the mean
Write centred(values) that returns a list of each value minus the mean of them all, rounded to two decimal places.
values - values.mean() does the whole thing. np.round then rounds the array, and tolist() turns it back into plain numbers.
Exercise 2: Apply a weight to every column
Write weighted_totals(table, weights) that multiplies each column of a 2-D array by the matching weight and returns one total per row, as a list. Let broadcasting apply the weights; do not loop over the columns.
(table * weights) scales every row by the weights, because the shapes line up on the right. Then sum along axis=1 for one total per row.