The T-Test › The Paired T-Test
Machine Learning from ScratchAll chapters 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:
- Independent design: Randomly assign people to training or control groups, compare group means
- 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:
where:
- = mean of the paired differences
- = standard deviation of the differences
- = number of pairs
Null hypothesis: (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.
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)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.


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:
# 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.")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.