The Chi-Square Goodness-of-Fit Test
You roll a die sixty times and jot down how often each face lands. A fair die should give roughly
ten of each — but you never get a perfect 10, 10, 10, 10, 10, 10. Some
faces come up a bit more, some a bit less, every single time. So the moment your tally looks
uneven, you face the oldest question in gambling:
is the die loaded, or is that just luck?
The chi-square goodness-of-fit test answers exactly this. You have a bunch of
observed counts spread across categories (the six faces, the colours in a bag of
sweets, the days of the week people are born on), and a hypothesised distribution that predicts
expected counts. The test boils the whole comparison down to a single number that
decides: does what I saw match what the model predicts — or is the mismatch too big to blame on
chance?
The idea: observed versus expected
This is a
hypothesis test, so
it runs on the same courtroom logic. The null hypothesis is the boring one — the
model fits:
H_0:\ \text{the data follow the hypothesised distribution.}
Under H_0 we can work out the expected count
E_i in each category: just the total number of observations times the
probability the model assigns to that category. For sixty rolls of a fair die, every face has
probability \tfrac16, so every
E_i = 60 \times \tfrac16 = 10.
Then we line the observed counts O_i up against those
expected counts and measure how far apart they are. The bars below are one run of sixty rolls — the
solid bar is what actually happened, the faint bar (and the dashed line) is what a fair die predicts.
That face-six spike is the thing the whole test is built to judge.
The test statistic
We need one number that summarises all six discrepancies at once. The natural move is to
add up the gaps (O_i - E_i) — but those cancel (the counts must total the
same either way), so we square each gap. And a gap of 3 matters far more when only
2 were expected than when 200 were, so we scale each squared gap by its expected
count. Summed over the categories, that is the chi-square statistic:
\chi^2 = \sum_i \frac{(O_i - E_i)^2}{E_i}.
Read it as a total squared, scaled discrepancy. Every term is
\ge 0, so \chi^2 is never negative. A perfect
fit (O_i = E_i everywhere) gives \chi^2 = 0;
the worse the mismatch, the bigger \chi^2 grows. So the
statistic is a single dial reading "how badly does the model fail?"
Worked example 1 — is the die loaded?
Sixty rolls gave the counts below. Every expected count is
E = 10. We build the sum term by term:
\begin{aligned}
\chi^2 &= \frac{(6-10)^2}{10} + \frac{(7-10)^2}{10} + \frac{(8-10)^2}{10} \\[2pt]
&\quad + \frac{(9-10)^2}{10} + \frac{(10-10)^2}{10} + \frac{(20-10)^2}{10} \\[4pt]
&= \frac{16 + 9 + 4 + 1 + 0 + 100}{10} = \frac{130}{10} = 13.0.
\end{aligned}
Notice how the face-six term, 100/10 = 10, dominates the whole sum — one
badly-fitting category can carry the verdict. Now for the degrees of freedom. There
are 6 categories and we estimated no parameters (the
fair-die probabilities were given, not fitted), so
\mathrm{df} = (\text{categories}) - 1 - (\text{estimated parameters}) = 6 - 1 - 0 = 5.
At the 5\% level the critical value for
\mathrm{df}=5 is about 11.07. Our
\chi^2 = 13.0 is bigger than that, so it falls in the upper
tail — the mismatch is too large to shrug off as luck. We reject
H_0: the evidence says this die is loaded.
Where does the cut-off come from?
When H_0 is true, the statistic
\chi^2 does not sit still — every fresh batch of rolls gives a slightly
different value. Across many honest batches those values trace out a known curve, the
chi-square distribution
with \mathrm{df}=5. Below is that curve. The shaded strip on the right is
the rejection region — the worst-fitting 5\% of outcomes,
everything past the critical value 11.07. Slide your own statistic and see
which side of the line it lands on:
A value inside the shaded tail is a value H_0 almost never produces — so
seeing one is strong evidence the model is wrong. A value out in the fat left part of the curve is
exactly what a good fit looks like, and we would fail to reject. Because only a large
\chi^2 counts against the model, this is always a one-sided,
upper-tail test.
Worked example 2 — do the sweet colours match?
A sweet company claims its bags are mixed in the proportions
24\% blue, 20\% orange,
16\% green, 14\% yellow,
13\% red and 13\% brown. You empty a bag of
100 and count the colours. Turn each claimed percentage into an
expected count first (100 \times \text{proportion}):
\begin{array}{l|cccccc}
\text{colour} & \text{blue} & \text{orange} & \text{green} & \text{yellow} & \text{red} & \text{brown} \\ \hline
\text{observed } O & 18 & 26 & 10 & 16 & 18 & 12 \\
\text{expected } E & 24 & 20 & 16 & 14 & 13 & 13
\end{array}
Both rows total 100 — a good sanity check. Now the statistic:
\begin{aligned}
\chi^2 &= \frac{(18-24)^2}{24} + \frac{(26-20)^2}{20} + \frac{(10-16)^2}{16} \\[2pt]
&\quad + \frac{(16-14)^2}{14} + \frac{(18-13)^2}{13} + \frac{(12-13)^2}{13} \\[4pt]
&= 1.50 + 1.80 + 2.25 + 0.29 + 1.92 + 0.08 \approx 7.84.
\end{aligned}
Here 6 categories and no fitted parameters again give
\mathrm{df} = 6 - 1 = 5 and the same critical value
11.07. This time 7.84 < 11.07, so we
fail to reject H_0: the bag is perfectly consistent with
the company's claimed mix. (The p-value is about
0.17 — a mismatch this size turns up around one bag in six by pure luck.)
The recipe, and degrees of freedom
Every goodness-of-fit test runs the same four steps:
- State H_0: the data follow the hypothesised distribution.
- Compute the expected counts E_i = n \times p_i for each category.
- Sum \chi^2 = \sum (O_i - E_i)^2 / E_i.
- Compare to the critical value (or find the upper-tail p-value) at your chosen level.
The one fiddly ingredient is the degrees of freedom. Start with the number of
categories, subtract 1 (once the first
k-1 counts are fixed, the last is forced, because they must add to
n), and subtract one more for every parameter you estimated from
the data to build the model. If, say, you had fitted a
binomial's
success probability from the same sample, that costs an extra degree of freedom:
\mathrm{df} = (\text{number of categories}) - 1 - (\text{number of estimated parameters}).
- Statistic: \chi^2 = \displaystyle\sum_i (O_i - E_i)^2 / E_i, over the categories — a total squared, scaled discrepancy between observed and expected counts.
- Null: H_0 says the data follow the hypothesised distribution; E_i = n\,p_i.
- Reference distribution: under H_0, \chi^2 approximately follows a chi-square distribution with \mathrm{df} = (\text{categories}) - 1 - (\text{estimated parameters}).
- Decision: a large \chi^2 (upper tail) is evidence the model is wrong ⇒ reject H_0. It is a one-sided test.
Three traps snare almost everyone the first time:
-
Use counts, never proportions or percentages. The formula divides by
E_i, so its scale depends on the sample size. Feeding it proportions
(numbers between 0 and 1) or percentages
gives a meaningless statistic. Always convert to actual counts:
O_i is a whole number of rolls/sweets/people, and
E_i = n \times p_i.
-
Expected counts must be reasonably large. The chi-square curve is only an
approximation to how the statistic really behaves, and it breaks down when some category
barely ever occurs. A common rule of thumb is that every
E_i \ge 5; if not, merge small categories together first.
-
It is one-sided — only a big \chi^2 rejects. A tiny
\chi^2 does not mean "something's wrong"; it means the fit is
excellent. We only ever shade the upper tail.
Picture the six die counts as six numbers that are free to wander — except they are chained together
by one rule: they must add up to 60. Fix any five of them and the sixth is
instantly pinned down. So only five of the counts are genuinely free to vary; that
is the -1.
Each parameter you estimate from the same data adds another chain. If the model's
probabilities weren't handed to you but were fitted — a mean, a success rate — you have spent some of
the data's freedom pinning the model to itself, so you pay one more degree of freedom per fitted
parameter. Fewer degrees of freedom pull the whole reference curve leftward, lowering the bar the
statistic must clear.
Goodness-of-fit checks one list of counts against a fixed distribution. But often the real
question is whether two characteristics are linked — does eye colour depend on hair colour,
does treatment depend on outcome? That cross-tabulated cousin, built from the very same
\sum (O-E)^2/E idea but with expected counts computed from row and column
totals, is the
chi-square test of independence.