An arithmetic line between two arrays crashes with
ValueError: operands could not be broadcast together with shapes (3,4) (3,)
(your two shapes will differ). The line looks mathematically reasonable — subtract
the means, add the adjustment, scale the columns — and it worked yesterday on a
different file.
First weeks with NumPy, usually while centring or scaling a table: subtract a row of means, divide by a spread, add a per-row correction. Also appears when two data sources drift out of step — one array lost a record during cleaning and the lengths no longer agree. Linked module: 0.4 (NumPy).
Broadcasting compares the two shapes from the RIGHT, one dimension pair at a time.
A pair is compatible when the sizes are equal, or one of them is 1; missing
dimensions on the shorter shape count as 1. So (3,4) with (4,) works — the 4s
line up and the 3 stretches. But (3,4) with (3,) fails: aligned from the right,
4 meets 3, and neither is 1. The error message already prints both shapes — read
them before touching code. Then classify the cause: (1) you reduced along the wrong
axis, so your means have the wrong length; (2) you have a row where you need a
column — (3,) instead of (3,1); (3) the two arrays genuinely disagree about how
many records exist, which is a data problem, not a shape problem. Confirm with two
prints: print(a.shape) and print(b.shape) directly above the crashing line.
Case 1: change the axis in the reduction — per-column stats need axis=0,
per-row stats need axis=1. Case 2: turn the row into a column with
b.reshape(-1, 1), or avoid the problem at the source by computing the reduction
with keepdims=True, which preserves the collapsed axis as size 1. Case 3: stop.
Do not slice one array shorter to force the maths through — find where a record was
dropped and fix the pipeline, or you will compute statistics over misaligned rows.
After any fix, print the result's shape and check it matches what you expected on
paper.
Print shape after every transformation while building — the reflex from module 0.4.
Write the expected shape as a comment on each pipeline step (# (6,4) -> (4,)).
Prefer keepdims=True on reductions you plan to broadcast back. When two arrays
must stay aligned, assert it once: assert a.shape[0] == b.shape[0] fails loudly at
the true cause instead of three lines later.
Q: "You subtract per-row means from a (3,4) matrix and get a broadcast error —
why, and what is the fix?" Strong answer: state the right-alignment rule in one
sentence, show why (3,) fails against (3,4) while (4,) succeeds, give both
fixes (reshape(-1,1) or keepdims=True), and add the warning that silently
trimming arrays to force a match hides real data misalignment — that last point
signals production experience.