Comparing two groups · Choose a method
Paired vs unpaired t-test: which one fits your experiment?
Use a paired t-test when each value in one group has a partner in the other — the same animal measured twice, or matched samples. Here is how to tell, and what choosing wrongly does.
On this page
Quick answer. Use a paired t-test when every value in one condition has a natural partner in the other: the same animal before and after treatment, left and right sides of the same subject, or samples matched in advance. Use an unpaired (independent-samples) test — Welch’s by default — when the two groups contain different, unrelated subjects. The choice is set by how the experiment was designed, not by which p-value is smaller.
Decide in three questions
- Was each subject measured in both conditions? The same mouse before and after a drug, the same culture with and without a treatment, the same patient at two visits: paired — with the two values lined up by subject in the same order.
- Were subjects matched in pairs before the experiment? Littermates split one to each group, or two halves of the same tissue sample: paired — the matching is part of the design.
- Otherwise — different subjects in each group, assigned independently: unpaired, using Welch’s t-test.
Treat data as paired only when the pairing is part of the design: six control mice and six treated mice are independent groups unless each control mouse was deliberately matched to one treated mouse, and equal group sizes alone are not enough. Write the pairing (or its absence) into the analysis plan before collecting data.
What the paired test actually does
A paired t-test is a one-sample t-test on the differences (Krzywinski & Altman 2014). For each subject it computes after − before, then asks whether the mean of those differences is far from zero, relative to how much the differences vary. With n pairs it has n − 1 degrees of freedom.
That is why pairing helps. Subjects often differ a lot from one another — some mice simply have higher glucose than others. The paired test removes that between-subject variation, because each subject is compared with itself. What is left is the variation in the change, which is usually much smaller. When you can measure each subject in both conditions, design the experiment that way: it usually needs fewer animals for the same power (try it in the sample size calculator).
Same mice, two answers
A constructed example: fasting glucose (mmol/L) in 8 mice, measured before and after a drug.
| Before | After | Difference | |
|---|---|---|---|
| Mean | 9.19 | 8.29 | −0.90 |
| SD | 1.86 | 1.67 | 0.58 |
The mice differ widely from one another (SD about 1.7–1.9 mmol/L), but each mouse’s change is consistent (SD of the differences 0.58). Before and after values are strongly correlated (r = 0.95).
from scipy import stats
before = [7.9, 10.4, 6.8, 12.1, 8.6, 11.0, 9.3, 7.4]
after = [7.4, 9.0, 6.9, 10.6, 7.2, 10.5, 8.6, 6.1]
paired = stats.ttest_rel(after, before) # correct: same mice
wrong = stats.ttest_ind(after, before, equal_var=False) # treats them as 16 different mice
print(paired.statistic, paired.df, paired.pvalue, paired.confidence_interval())
print(wrong.statistic, wrong.df, wrong.pvalue)
| Analysis | t | df | p | 95% CI for the change |
|---|---|---|---|---|
| Paired t-test (correct) | −4.37 | 7 | 0.003 | −1.39 to −0.41 mmol/L |
| Unpaired Welch (wrong here) | −1.02 | 13.8 | 0.33 | −2.80 to 1.00 mmol/L |
In R the paired test is t.test(after, before, paired = TRUE), or equivalently t.test(after - before); both give t = −4.37, df = 7, p = 0.0033.
What changed. Both analyses estimate the same average change, −0.90 mmol/L. The unpaired test compares the spread of 16 values that include all the differences between mice, so the drug’s consistent effect drowns in that noise (p = 0.33). This is the general pattern: when paired values are positively correlated, a two-sample test applied to them is conservative and loses power (Krzywinski & Altman 2014). The paired test looks only at each mouse’s own change and finds it clearly (p = 0.003, interval well away from zero).
The reverse mistake matters too. Pairing values that are not truly paired — for example, lining up control and treated mice in the order they were measured — invents a structure that does not exist. The degrees of freedom and the p-value then describe a design you did not run. Decide pairing from the protocol, before analysis.
Check what your software or AI ran
| Software | Paired | Unpaired |
|---|---|---|
R t.test |
t.test(after, before, paired = TRUE); formula route t.test(Pair(after, before) ~ 1) (R ≥ 4.0; R ≥ 4.4 refuses paired = with a formula) |
t.test(treated, control) or t.test(value ~ group) (Welch by default) |
SciPy stats |
ttest_rel(after, before) |
ttest_ind(treated, control, equal_var=False) |
| GraphPad Prism | Paired t test (or ratio paired t test when the treatment effect is proportional) | Unpaired; Welch’s t test is the default in Prism 10 and 11 |
R 4.4.0 changed the formula interface. Older code and many tutorials write t.test(value ~ time, data = d, paired = TRUE). Since R 4.4.0 the formula methods of t.test() and wilcox.test() refuse the paired argument; the R NEWS entry says to use Pair(x1, x2) ~ 1 for a paired test (R 4.4.0 NEWS). If AI-written or inherited code fails with this error, rewrite it with Pair() or the two-vector form; deleting paired = TRUE to make the error go away silently turns it into an unpaired test. With long-format data (one row per measurement), reshape to one row per mouse first:
# d has columns mouse, time ("before"/"after") and glucose
w <- reshape(d, idvar = "mouse", timevar = "time", direction = "wide")
t.test(Pair(glucose.after, glucose.before) ~ 1, data = w) # paired, any R version from 4.0
Quick checks on a result you were given:
- Degrees of freedom. A paired test on n subjects reports df = n − 1 (7 for 8 mice). An unpaired test on the same data reports a larger df (14, or a decimal near it for Welch).
- Order matters for paired data. The two arrays must list the same subject in the same position. Sorting either column, or dropping a subject from one column only, silently breaks the pairs.
- Missing values. If one measurement of a pair is missing, that subject cannot enter a paired t-test. Check how many pairs were actually used; when many are incomplete, a mixed model that uses every available value is the better tool. (Our engineering team reproduced a library whose paired t-test still counted missing pairs in its degrees of freedom and reported it upstream; confirmation is pending.)
A precise request to an AI assistant avoids the most common slip — getting an independent-samples test on paired data:
Each of the [n] mice was measured before and after treatment; the two lists below are in
the same mouse order. Run a paired t-test on after − before (scipy.stats.ttest_rel or
R t.test(paired = TRUE)). Report the mean difference with its 95% confidence interval,
t, df and the exact p-value.
When the paired t-test needs more thought
- More than two time points or conditions. Repeated t-tests between pairs of time points inflate false positives; use a repeated-measures model (repeated-measures ANOVA or a mixed model).
- Clearly skewed differences with few pairs. The paired t-test assumes the differences are roughly normal. With few pairs and a clearly skewed or outlying difference, consider the Wilcoxon signed-rank test, or analyse ratios on the log scale when effects are proportional (the logic behind Prism’s ratio paired t test).
- A control group as well as before/after. If treated and control groups were each measured before and after, the question is whether the change differs between groups. For randomised groups, analyse the final values with the baseline as a covariate (ANCOVA); Welch’s t-test on the change scores is a simpler alternative. Two separate paired tests, one per group, answer a different question. See change from baseline vs ANCOVA.
In each case, name the analysis in your plan before the data come in.
Report it so a reviewer can check it
Reviewers need to know which test you used. In a review of physiology papers, 53% of those that used t-tests (95 of 179) did not say whether any of them were paired or unpaired (Weissgerber et al. 2018, Results).
Methods sentence (keep the bracketed parts only if true):
Glucose before and after treatment was compared with a two-sided paired t-test on the within-mouse differences (n = [8] mice)[, specified before the data were analysed].
Results sentence (the example above):
Fasting glucose fell from 9.19 mmol/L (SD 1.86) to 8.29 mmol/L (SD 1.67) in 8 mice; mean change −0.90 mmol/L (SD of changes 0.58), 95% CI −1.39 to −0.41; paired t(7) = −4.37, p = 0.003.
Report the mean change and its interval first; it is the effect. Plotting each mouse as a line from before to after shows the pairing far better than two bars.
Corrections
- 11 November 2026: for treated and control groups each measured before and after, the guide now recommends ANCOVA on the final values (baseline as covariate) first, following change from baseline vs ANCOVA; the earlier version offered Welch’s t-test on change scores or a group-by-time model. Change scores remain a valid, simpler alternative.
References
- Krzywinski M, Altman N (2014). Points of significance: Comparing samples — part I. Nature Methods 11(3):215–216. doi:10.1038/nmeth.2858
- R Core Team. NEWS for R 4.4.0: formula methods of
t.test()andwilcox.test()andpaired(PR#14359). R NEWS - Weissgerber TL, Garcia-Valencia O, Garovic VD, Milic NM, Winham SJ (2018). Why we need to report more than ‘Data were analyzed by t-tests or ANOVA’. eLife 7:e36163. doi:10.7554/eLife.36163
- Software documentation accessed 10 November 2026: SciPy 1.18
scipy.stats.ttest_relandttest_ind; Rstats::t.test; GraphPad Prism Statistics Guide and Knowledgebase (paired and ratio paired t tests: the ratio test analyses the logarithm of treated ÷ control).
How this page was made
- Written and published by Licklider. Recommendations cite peer-reviewed methods papers and official software documentation listed under References; cited figures were checked against the source text.
- The worked example uses constructed data. Its numbers were produced by stored code (Python with SciPy 1.18.1; R 4.3.3), and the two implementations agree.
- Separate review passes checked the statistics, the citations and readability before publication.