The T-Test › The Paired T-Test

Michael BrenndoerferJanuary 3, 20265 min read
Machine Learning from ScratchAll chapters
Part 2 of 9Hypothesis Testing
Chapter 15The T-Test › The Paired T-Test
Reading section 6 of 11 · The Paired T-Test · 5 minSection 6 of 11 · 5 min

Book contents

Section 6 of 11 · 5 min read

The T-Test › The Paired T-TestOne section · Sections in this chapter6 / 11 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The paired t-test is used when observations come in matched pairs, where each pair shares some characteristic that makes them non-independent. Common scenarios include:

  • Before-after measurements: Same subjects measured twice
  • Matched case-control studies: Cases matched to controls on key characteristics
  • Twin studies: Comparing outcomes between twins
  • Left-right comparisons: Same subject, different sides

Why Pairing Matters

Consider testing whether a training program improves performance. You could:

  1. Independent design: Randomly assign people to training or control groups, compare group means
  2. Paired design: Measure each person before and after training, analyze the changes

The paired design is often more powerful because it eliminates between-subject variability. People differ enormously in baseline ability, but by looking at changes within each person, we focus only on the training effect.

The Mathematics

The paired t-test is simply a one-sample t-test on the differences:

di=xi,after−xi,befored_i = x_{i,\text{after}} - x_{i,\text{before}}

Test statistic:

t=dˉsd/nt = \frac{\bar{d}}{s_d / \sqrt{n}}

where:

  • dˉ\bar{d} = mean of the paired differences
  • sds_d = standard deviation of the differences
  • nn = number of pairs
  • df=n−1df = n - 1

Null hypothesis: H0:μd=0H_0: \mu_d = 0 (no average change)

Worked Example: Blood Pressure Medication

A study tests whether a new medication reduces blood pressure. Ten patients have their systolic blood pressure measured before starting medication and again after 4 weeks of treatment.

In[11]:
Code
import numpy as np
from scipy import stats

# Blood pressure measurements (mmHg)
before = np.array([145, 152, 148, 155, 160, 142, 158, 165, 150, 155])
after = np.array([138, 145, 140, 150, 152, 140, 148, 158, 145, 148])

# Step 1: Calculate differences (after - before)
differences = after - before
n = len(differences)

# Step 2: Calculate mean and std of differences
d_bar = np.mean(differences)
s_d = np.std(differences, ddof=1)

# Step 3: Calculate standard error
se_d = s_d / np.sqrt(n)

# Step 4: Calculate t-statistic
t_stat = d_bar / se_d
df = n - 1

# Step 5: Calculate p-value (two-sided)
p_value = 2 * stats.t.sf(abs(t_stat), df=df)

# Step 6: Confidence interval for mean change
t_crit = stats.t.ppf(0.975, df=df)
ci = (d_bar - t_crit * se_d, d_bar + t_crit * se_d)

# Verify with scipy
t_scipy, p_scipy = stats.ttest_rel(after, before)
Out[12]:
Console
Paired T-Test: Blood Pressure Medication Study
============================================================

Data (n = 10 patients):
------------------------------------------------------------
Before: [np.int64(145), np.int64(152), np.int64(148), np.int64(155), np.int64(160), np.int64(142), np.int64(158), np.int64(165), np.int64(150), np.int64(155)]
After:  [np.int64(138), np.int64(145), np.int64(140), np.int64(150), np.int64(152), np.int64(140), np.int64(148), np.int64(158), np.int64(145), np.int64(148)]
Change: [np.int64(-7), np.int64(-7), np.int64(-8), np.int64(-5), np.int64(-8), np.int64(-2), np.int64(-10), np.int64(-7), np.int64(-5), np.int64(-7)]

Step-by-step calculation:
------------------------------------------------------------
1. Mean change:     d_bar = -6.60 mmHg
2. Std of changes:  s_d = 2.17 mmHg
3. Standard error:  SE = s_d/sqrt(n) = 2.17/sqrt(10) = 0.69
4. T-statistic:     t = d_bar/SE = -6.60/0.69 = -9.616
5. Degrees of freedom: df = n - 1 = 9
6. P-value (two-sided): 0.000005

95% CI for mean change: [-8.15, -5.05] mmHg

Interpretation:
------------------------------------------------------------
The average blood pressure decreased by 6.6 mmHg (p < 0.001).
We are 95% confident the true mean reduction is between
5.0 and 8.2 mmHg.
Out[13]:
Visualization
Paired data plot showing before and after blood pressure measurements connected by lines.
Individual patient changes in blood pressure before and after medication. Each line connects measurements from the same patient. The consistent downward slope indicates most patients experienced a reduction.
Histogram showing distribution of blood pressure changes.
Distribution of changes in blood pressure. The paired t-test detects this reduction with high significance (p < 0.001).

Why Not Use an Independent T-Test?

You might wonder: what if we ignored the pairing and used an independent two-sample t-test? Let's compare:

In[14]:
Code
# Paired t-test (correct)
t_paired, p_paired = stats.ttest_rel(after, before)

# Independent t-test (ignoring pairing)
t_indep, p_indep = stats.ttest_ind(after, before)

print("Comparison of paired vs. independent analysis:")
print("-" * 50)
print(f"Paired t-test:      t = {t_paired:.3f}, p = {p_paired:.6f}")
print(f"Independent t-test: t = {t_indep:.3f}, p = {p_indep:.4f}")
print()
print("The paired test is much more powerful because it eliminates")
print("between-subject variability, focusing only on within-subject changes.")
Out[14]:
Console
Comparison of paired vs. independent analysis:
--------------------------------------------------
Paired t-test:      t = -9.616, p = 0.000005
Independent t-test: t = -2.233, p = 0.0385

The paired test is much more powerful because it eliminates
between-subject variability, focusing only on within-subject changes.

The paired test detects the effect with much higher confidence because it accounts for the correlation between before and after measurements within each subject.