library(rstatix)
data("antismoking", package = "datarium")
xtab <- xtabs(~ before + after, data = antismoking)
xtab after
before non.smoker smoker
non.smoker 25 6
smoker 21 10
Test whether a proportion changed between two paired measurements — the categorical paired test for before/after designs, with the exact version for small samples
Learn to run McNemar’s test in R — the test for comparing paired proportions, the categorical equivalent of the paired t-test for a before/after or matched design. Build the 2×2 paired table with base R, run rstatix mcnemar_test(), and use the exact binomial version when the discordant counts are small.
June 23, 2026
July 7, 2026
rstatix::mcnemar_test() on the 2×2 paired table.binom_test() on the discordant counts).McNemar’s test compares two paired proportions — the same subjects measured twice, in a before/after design or a matched study. It is the categorical analogue of the paired t-test: instead of two independent groups (which would call for a chi-square test), the two measurements come from the same people.
The trick: only the subjects who changed (the discordant pairs — yes→no and no→yes) tell you whether the proportion shifted. The scenario here: did an anti-smoking intervention change the proportion of smokers, measured before and after? This lesson runs it with rstatix on the antismoking data.
McNemar’s test hypotheses. Labelling the 2×2 paired table’s off-diagonal cells B and C (the two kinds of change), H₀: B = C (equal numbers changed each way → no net change). Hₐ: B ≠ C (the proportion changed).
We use the antismoking dataset from datarium — 62 people whose smoking status was recorded before and after an intervention. Cross-tabulate into the paired 2×2 table with base R:
after
before non.smoker smoker
non.smoker 25 6
smoker 21 10
The diagonal (25 stayed non-smokers, 10 stayed smokers) are the concordant pairs — no change. The off-diagonal are the discordant pairs: 6 went non-smoker → smoker, and 21 went smoker → non-smoker. McNemar’s test asks whether those two numbers (6 vs 21) differ.
# A tibble: 1 × 6
n statistic df p p.signif method
* <int> <dbl> <dbl> <dbl> <chr> <chr>
1 62 7.26 1 0.00705 ** McNemar test
There was a significant change in smoking status, χ²(1) = 7.26, p = 0.007 — far more people quit (21) than started (6), so the proportion of non-smokers rose after the intervention.
McNemar’s chi-square is a large-sample approximation. When the total number of discordant pairs (B + C) is small (≲ 20), use the exact binomial test — under H₀, each discordant pair is equally likely to go either way, so the count tests against p = 0.5:
# A tibble: 1 × 6
n estimate conf.low conf.high p p.signif
* <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 27 0.222 0.0862 0.423 0.00592 **
The exact test agrees (p = 0.006). Here B + C = 27 so chi-square is fine, but for fewer discordant pairs the exact version is the safe choice.
library(rstatix)
library(ggpubr)
data("antismoking", package = "datarium")
n <- nrow(antismoking)
long <- data.frame(
time = factor(rep(c("before", "after"), each = n), levels = c("before", "after")),
status = c(as.character(antismoking$before), as.character(antismoking$after))
)
stat.test <- mcnemar_test(xtabs(~ before + after, data = antismoking))
ggbarplot(as.data.frame(table(long)), x = "time", y = "Freq", fill = "status",
palette = "jco", ylab = "Count", xlab = NULL) +
labs(subtitle = get_test_label(stat.test, detailed = TRUE))
A McNemar’s test showed a statistically significant change in smoking status before vs after the intervention, χ²(1) = 7.26, p = 0.007: of the participants who changed, 21 quit smoking while only 6 took it up.
McNemar’s statistic uses only the discordant counts B and C: \(\chi^2 = \dfrac{(B - C)^2}{B + C}\) (with a continuity correction, \(\dfrac{(|B - C| - 1)^2}{B + C}\)), compared to a chi-square distribution with 1 degree of freedom. The concordant cells (A and D) cancel out because they carry no information about change. Under H₀ the \(B + C\) changers split 50/50, which is exactly the exact-binomial formulation.
Run McNemar’s test on your own paired 2×2 table — e.g. approval before vs after a campaign. Edit the counts and re-run; the sandbox boots on first Run.
Ask Prova “I measured the same subjects before and after — test whether the proportion changed with McNemar’s test” — it answers with rstatix code you can run on your own paired table. The runtime is the judge. Ask Prova →
You used a chi-square test on paired data. The ordinary chi-square test assumes the two groups are independent. For the same subjects measured twice (before/after, matched), use McNemar’s test — it accounts for the pairing by looking only at who changed.
You looked at the diagonal. McNemar ignores the concordant pairs (no change) — only the off-diagonal discordant counts matter. A table with huge diagonals but B ≈ C shows no significant change.
Few discordant pairs. When B + C is small (≲ 20), the chi-square approximation is shaky — report the exact binomial result instead.
McNemar’s test compares two paired proportions — the same subjects measured twice (before/after) or matched pairs, on a yes/no outcome. It tests whether the proportion changed between the two measurements, making it the categorical equivalent of the paired t-test.
The chi-square test of independence compares two independent groups; McNemar’s test compares the same subjects measured twice (paired data). McNemar uses only the discordant (changed) pairs, which is how it accounts for the pairing — using a chi-square test on paired data would be wrong.
When the total number of discordant pairs (B + C) is small — roughly 20 or fewer. The chi-square version is a large-sample approximation; below that, the exact binomial test (each discordant pair tested against p = 0.5) gives the correct p-value.
Fill the blank with mcnemar_test. For question 2, recall that McNemar ignores the diagonal and depends on how different B and C are.
For question 2: no — McNemar uses only the discordant pairs, and B = 8 vs C = 9 are almost equal, so there’s no evidence of net change regardless of the large concordant diagonal. The 200 unchanged subjects are irrelevant to the test.
You can now run McNemar’s test in R: cross-tabulate the paired before/after data into a 2×2 table, run mcnemar_test(), and read the discordant counts — it tests whether the proportion changed between two paired measurements. Use the exact binomial version when the number of changers is small, and step up to Cochran’s Q for three or more repeated measures.
Prove you can do it. Master the whole Categorical Analysis in R series — track your path, build projects, and earn a certificate.
Go Pro — unlimited Prova on your own data and a verifiable certificate that proves the skill.
from $15/mo billed yearly
✓ You're Pro — keep going. The runtime is the judge.
Get new R & Python lessons by email
Practical, reproducible, no spam. Unsubscribe anytime.
Double opt-in. We never share your email.
Every result on this page was produced by the code shown, run at build time against a pinned R environment — edit any block and Run to reproduce it yourself.
@online{2026,
author = {},
title = {McNemar’s {Test} in {R:} {Compare} {Paired} {Proportions}
{(Before/After)}},
date = {2026-06-23},
url = {https://www.datanovia.com/learn/biostatistics/categorical/mcnemar-test-in-r},
langid = {en}
}