Chi-Square Test of Independence
A clinic records two things about every patient: whether they were vaccinated, and
whether they later fell sick. The counts land in a tidy
two-way table. Now the
real question: are these two things linked — does vaccination relate to getting sick — or is the
table just noise, the counts scattered the way pure chance would scatter them?
The chi-square test of independence answers exactly this. It takes a contingency table
of two categorical variables and asks whether they are associated (knowing one tells
you something about the other) or independent (they drift apart with no connection). It
reuses the very same statistic you met in the
goodness-of-fit test
— \chi^2 = \sum \dfrac{(O - E)^2}{E} — but with a clever new way of building
the expected counts E.
The null hypothesis: independence
We start by assuming there is no link. That is the null hypothesis:
- H_0: the two variables are independent (no association).
- H_1: the two variables are associated (some dependence).
If two variables really are independent, probability has a rule for how the counts should split.
The chance of landing in a given row and a given column is just the row's share times the
column's share. Multiply that probability by the grand total N and you get the
expected count for that cell:
E = N \cdot \frac{\text{row total}}{N} \cdot \frac{\text{column total}}{N}
= \frac{\text{row total} \times \text{column total}}{\text{grand total}}.
Every cell gets its own E from its own row and column totals. The observed
counts O are what actually happened. If the two variables truly are
independent, each O should sit close to its E; big
gaps are the fingerprint of an association.
Worked example 1: vaccination and illness (a 2×2 table)
Two hundred people, split by vaccination and by whether they got sick. First the
observed counts, with all the margins:
| Sick | Well | Row total |
| Vaccinated | 10 | 90 | 100 |
| Unvaccinated | 30 | 70 | 100 |
| Column total | 40 | 160 | 200 |
Now the expected count in each cell, using
E = \dfrac{\text{row} \times \text{col}}{200}:
- Vaccinated & Sick: E = \dfrac{100 \times 40}{200} = 20.
- Vaccinated & Well: E = \dfrac{100 \times 160}{200} = 80.
- Unvaccinated & Sick: E = \dfrac{100 \times 40}{200} = 20.
- Unvaccinated & Well: E = \dfrac{100 \times 160}{200} = 80.
Notice the expected counts keep the same margins (each row still totals 100, each column 40 and
160) — they just spread the totals as if there were no link. Here is the observed count over its
expected count, cell by cell:
| Sick (O / E) | Well (O / E) |
| Vaccinated | 10 / 20 | 90 / 80 |
| Unvaccinated | 30 / 20 | 70 / 80 |
Add up \dfrac{(O - E)^2}{E} across all four cells:
\chi^2 = \frac{(10-20)^2}{20} + \frac{(90-80)^2}{80}
+ \frac{(30-20)^2}{20} + \frac{(70-80)^2}{80} = 5 + 1.25 + 5 + 1.25 = 12.5.
The degrees of freedom for an r \times c table are
(r-1)(c-1). This table is 2 \times 2, so
df = (2-1)(2-1) = 1, and the 5% critical value is
3.84. Since 12.5 > 3.84, we
reject independence: there is an association between vaccination and illness in
this data.
Seeing it: observed against expected
Put the observed count (solid) beside the expected count (pale) for each of the four cells. Where the two
bars in a pair pull apart, that cell pumps up \chi^2; where they match, it
contributes almost nothing.
The two Sick cells swing hardest — vaccinated people were much less sick than independence would
predict (10 vs 20), unvaccinated much more (30 vs 20). Those two gaps, squared and scaled, are what push
the total to 12.5.
Worked example 2: a drug that doesn't beat the placebo
Not every table hides an association. A trial gives 60 people a drug and 60 a placebo, then records who
recovered:
| Recovered | Not | Row total |
| Drug | 45 | 15 | 60 |
| Placebo | 40 | 20 | 60 |
| Column total | 85 | 35 | 120 |
Expected counts, again \dfrac{\text{row} \times \text{col}}{120}:
- Drug & Recovered: \dfrac{60 \times 85}{120} = 42.5; Drug & Not: \dfrac{60 \times 35}{120} = 17.5.
- Placebo & Recovered: 42.5; Placebo & Not: 17.5.
\chi^2 = \frac{(45-42.5)^2}{42.5} + \frac{(15-17.5)^2}{17.5}
+ \frac{(40-42.5)^2}{42.5} + \frac{(20-17.5)^2}{17.5} \approx 0.15 + 0.36 + 0.15 + 0.36 = 1.01.
Still df = 1, still comparing to 3.84. But now
1.01 < 3.84, so we fail to reject
H_0. The recovery difference (45 vs 40) is small enough to be ordinary chance —
this data gives no evidence that the drug and recovery are associated.
Reading the verdict carefully
A significant result (example 1) says the two variables move together — and that is
all it says. Three warnings live inside that one sentence:
-
Association is not causation. Vaccination being linked to less illness does
not, by itself, prove the vaccine caused it — some hidden third factor (age, health, caution)
could drive both. The test finds a pattern; explaining it is a separate job.
-
It doesn't say which cell. \chi^2 is one number for the
whole table. It flags that somewhere observed and expected disagree, but you must inspect the
cells (or their contributions) to see where the action is.
-
It doesn't measure strength. A big \chi^2 can come from a
weak association in a huge sample; effect-size measures (like Cramér's V) are needed to judge how
strong the link is.
-
Tests whether two categorical variables in a contingency table are
associated (H_1) or independent
(H_0).
-
Expected count per cell (assuming independence):
E = \dfrac{\text{row total} \times \text{column total}}{\text{grand total}}.
-
Statistic (summed over every cell):
\chi^2 = \displaystyle\sum \frac{(O - E)^2}{E}.
-
Degrees of freedom for an r \times c table:
df = (r-1)(c-1).
-
A large \chi^2 (beyond the critical value) → reject
independence: there is evidence of an association.
-
Expected counts, not "categories − 1". Each E comes from
row total × column total ÷ grand total — never from a single margin. And the degrees of freedom
are (r-1)(c-1), not "number of categories − 1" as in the
goodness-of-fit test. For a 3 \times 4 table that's
(3-1)(4-1) = 6, not 11.
-
Association is never causation. A tiny p-value proves the variables are linked in the
data, not that one makes the other happen.
-
Small expected counts break it. The \chi^2 approximation
needs every expected count to be reasonably large — a common rule is E \geq 5
in each cell. If some cells fall short, the approximation is unreliable; reach for
Fisher's exact test instead (or combine categories).
Goodness-of-fit asks "does one variable match a claimed distribution?"; independence asks "do two
variables move together?". They feel different, yet both reduce to counts we saw versus
counts a model predicts — and \sum (O-E)^2/E measures that mismatch
either way. The only thing that changes is where the expected counts come from: a stated
distribution for goodness-of-fit, or the row-and-column margins for independence. Same ruler, different
thing being measured.