McNemar's test calculator
For the paired counts 59, 6, 16 and 80, McNemar's test uses only the 22 discordant pairs and gives a p-value just above 0.05, so the change is not significant at the 5% level. Continuity correction is on by default. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- A
- 59
- B
- 6
- C
- 16
- D
- 80
- N
- 161
- N discordant
- 22
- Chi square
- 3.6818181818
- P value
- 0.0550088336
McNemar's test asks whether two paired binary classifications disagree in a systematic way. You observe the same subjects twice—before and after a treatment, two raters scoring the same cases, or two diagnostic tests on the same patients—and you fold those pairs into a 2x2 table. Concordant pairs sit on the diagonal and do not inform the null; only the two discordant cells, conventionally named b and c, enter the chi-square statistic. This calculator accepts the four non-negative integer cell counts of that paired table, rejects a negative count instead of silently clipping it, and returns the McNemar chi-square statistic with one degree of freedom together with the corresponding upper-tail p-value. Continuity correction is on by default, matching the Edwards form used by common statistical packages; you can turn it off to recover the original 1947 ratio of the squared discordant difference over the discordant total.
How McNemar's test is defined on a paired 2x2 table
Write the four observed pair counts in the usual textbook layout: a in the top-left cell for first-yes and second-yes, b top-right for first-yes and second-no, c bottom-left for first-no and second-yes, and d bottom-right for first-no and second-no. Cells a and d are concordant: those subjects did not change classification, so they cancel out of the test of marginal homogeneity. Cells b and c are the discordant pair counts, and McNemar's argument conditions on their sum.
Under the null that the two marginal probabilities of a positive result are equal, each discordant pair is equally likely to fall in b or in c, so the expected counts are equal and the Pearson residual collapses to the one-degree-of-freedom chi-square (b minus c) squared over (b plus c).
The Edwards continuity correction, applied by default when the absolute difference of b and c is greater than one, replaces that numerator with the square of the absolute difference minus one, which reduces the statistic slightly and is the default in several widely used statistical packages. The p-value is the upper tail of a chi-square distribution with one degree of freedom, equivalently the complementary error function of the square root of half the statistic, computed here through the regularized incomplete gamma so no printed table is required.
Where a paired McNemar chi-square shows up in real work
Introductory biostatistics and AP-statistics courses constantly assign before-and-after binary drills—treatment versus control on the same subjects, exposed versus unexposed at two visits, recovered versus still ill after a course of therapy—where a chi-square test of independence would treat the two margins as unrelated samples and a paired t-test would demand a numeric change score that does not exist.
Clinical and epidemiology teams still report McNemar's chi-square for matched case-control pairs, two diagnostic tests on the same patients, and pre/post adverse-event flags when the scientific question is whether the two paired margins differ. Quality and reliability engineers compare pass/fail on the same units before and after a process change and need the discordant-pair statistic rather than an unpaired two-proportion z-test that ignores the matching. Two raters scoring the same items as yes or no produce a paired 2x2 whose off-diagonal cells are exactly the McNemar inputs.
If you later need Fisher's exact test on an unpaired 2x2, a paired t-test on numeric before-and-after measurements, or a confidence interval for a paired mean difference, treat those as separate search intents and landings rather than overloading this McNemar's test calculator page.
What you can do with it
Paired 2x2 homework checks
Students and graders verify the McNemar chi-square and one-df p-value from four integer cells without scanning a chi-square table or mixing up discordant counts.
Matched clinical and diagnostic tables
Analysts test whether two paired binary margins differ—two tests on the same patients, or case-control pairs—when only b and c inform the null.
Before/after pass-fail on the same units
Engineers compare a binary classification on identical items before and after a process change and publish the discordant-pair chi-square and p-value.
FAQ
Which cells of the 2x2 table enter the statistic?
Only the discordant pair counts b (first yes, second no) and c (first no, second yes). Concordant cells a and d are echoed in the response and in the grand total n, but they cancel out of the chi-square.
Is continuity correction applied?
Yes by default. When correction is true and |b−c| is greater than one, the engine uses the Edwards form (|b−c|−1)²/(b+c). Set correction to false for the original (b−c)²/(b+c) statistic.
What happens if a cell is negative or not an integer?
McNemar's test is defined on non-negative integer pair counts; fractions and negative frequencies are rejected instead of being rounded or clipped.
How is this different from Fisher's exact test or a paired t-test?
Fisher's exact test treats an unpaired 2x2 of independent samples. A paired t-test needs numeric before/after measurements. McNemar's test is the chi-square for two paired binary classifications on the same subjects.
What does it cost?
The browser tool is free and runs locally.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/stat/mcnemars-test \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"a":59,"b":6,"c":16,"d":80}'const res = await fetch("https://api.kit.forhosting.com/stat/mcnemars-test", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"a": 59,
"b": 6,
"c": 16,
"d": 80
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/stat/mcnemars-test",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"a": 59,
"b": 6,
"c": 16,
"d": 80
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/stat/mcnemars-test", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"a":59,"b":6,"c":16,"d":80}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"a":59,"b":6,"c":16,"d":80}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/stat/mcnemars-test", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"a": 59,
"b": 6,
"c": 16,
"d": 80
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "stat.mcnemars_test",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_cell | 10000000 |
max_n | 40000000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Successful API calls are billed at the published base of $0.002 per item; invalid input is not charged.
How McNemar's test is defined on a paired 2x2 table
When b plus c is zero the ratio is undefined and the request is rejected rather than inventing a p-value of one.
What you send and what you get back
Send four required non-negative integer cell counts named a, b, c and d. A negative count is rejected because a contingency table cannot hold a negative frequency. A non-integer count is rejected because McNemar's test is defined on discrete pair counts, not on silently rounded measurements. Classic checks include the paired table fifty-nine, six, sixteen, eighty, whose continuity-corrected chi-square is eighty-one over twenty-two, and a deliberate negative cell that must fail. The engine also accepts the matrix aliases n11, n12, n21, n22 and a11, a12, a21, a22 so a script that already stores a numeric matrix does not have to rename fields. An optional boolean correction, also accepted as continuity_correction or correct, defaults to true and selects the Edwards form; set it to false for the uncorrected 1947 statistic. Each count may arrive as a JSON integer or as a digit string; fractions, booleans, NaN, Infinity, empty strings and missing fields fail with invalid_input that names the offending cell. If both discordant cells are zero the statistic is undefined and the request fails instead of dividing by zero. On success the response echoes the four cells, the grand total n, the discordant total n_discordant, the chi_square statistic rounded to twelve decimal places, the one-degree-of-freedom p_value, df equal to one, the correction flag that was applied, a significant_at_05 flag at the conventional alpha of 0.05, a method label, and a short formula string. Wire the free browser form for homework and demos, then call the identical contract from scripts when you need many paired 2x2 tests under one JSON shape. API pricing for successful calls is the published base of $0.002 per item; validation failures do not consume balance and never invent a chi-square stand-in to force a number.
Where a paired McNemar chi-square shows up in real work
A single trusted oracle that returns cleaned JSON speeds grading without looking up one-degree-of-freedom tails by hand. Because this capability is a pure parse engine, API pricing is the published base of $0.002 per successful item and failed validation does not consume balance.