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:

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}).

Three traps snare almost everyone the first time:

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.