Paired T-Test
The engine for Internal Discovery. This model audits the change within the same participants (e.g., Pre-test vs. Post-test), using each individual as their own baseline to reveal pure recovery signals.
What is it?
Paired Samples T-Test compares the means of two dependent, linked measurements taken from the identical subjects (e.g. Pre-Test vs. Post-Test scores).
When to use it
- Before & After: Track performance shift within individuals over time.
- Matched Pairs: Subjects are matched (e.g., twins, sibling pairs).
Core Idea
Instead of comparing two broad group spreads, we isolate and track the individual changes (slopes) directly within each subject:
By focusing exclusively on the within-subject differences, we strip away individual baseline differences, vastly increasing statistical power.
Hypotheses
How it works
- Compute difference (d = Post - Pre) for each individual.
- Find average difference (d-bar) and standard deviation of differences (s_d).
- Calculate Standard Error: SE = s_d / sqrt(N).
- Compute t = d-bar / SE. Test against df = N - 1.
Assumptions
Effect Size
Standardized shift is measured with Cohen's d for paired samples: d = d-bar / s_d. Benchmarks: 0.2 (small), 0.5 (medium), and 0.8 (large).
Quick Example
| Subject | Pre-Test Score | Post-Test Score |
|---|---|---|
| S1 | 72.0 | 78.0 (+6.0) |
| S2 | 68.0 | 74.0 (+6.0) |
| Mean Shift | +6.0 (p = 0.008) | |
Paired Slope Line Live Laboratory
Change the average pre-to-post shift and difference SD to watch parallel slopes split or cross.
| Metric | Value |
|---|---|
| Mean Difference (D-bar) | 3.5764 |
| Difference SD (s_D) | 3.1366 |
| t-statistic | 3.9497 |
| p-value | 0.0001 |
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: μD = 0 (mean difference between paired observations is zero)
Hₐ: μD ≠ 0 (mean difference is not zero)
Tests mean of difference scores. Can be one-tailed if directional change predicted.
Assumptions
The core mathematical criteria needed to ensure that statistical testing remains unbiased and valid.
Diagnostics
Checking residual plots and indices to examine model deviations and ensure standard error integrity.
- Q-Q plot of difference scores to assess normality
- Boxplot of differences to identify outliers
- Shapiro-Wilk test on differences (if n < 50)
- Histogram of difference scores
- Scatter plot of Time1 vs Time2 (with identity line)
- Descriptive statistics of differences (M, SD, n)
- Check skewness and kurtosis of differences
- Profile plot showing individual trajectories
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Pre-Post Cognitive Behavioral Therapy for Depression (Classic RCT)
Research question: Does 12-week CBT reduce depression symptoms? Design: Pre-post RCT with n=35 participants. Outcome: Beck Depression Inventory-II (BDI-II) score at baseline and post-treatment (continuous, 0-63, higher = more depressed). Classic paired design testing within-subject change.
# Paired-samples t-test: Pre-Post CBT for Depression
# Based on realistic effect sizes from CBT meta-analyses
# Install/load packages
library(ggplot2)
library(effsize)
library(tidyr)
# Simulate realistic data (or load: data <- read.csv("cbt_depression.csv"))
set.seed(2025)
n <- 35
data <- data.frame(
subject_id = 1:n,
pre_BDI = rnorm(n, mean=28.5, sd=8.2), # Baseline: M=28.5 (moderate-severe depression)
post_BDI = rnorm(n, mean=16.3, sd=9.1) # Post-CBT: M=16.3 (mild depression)
)
# IMPORTANT: Add within-subject correlation (r=.65) to make data realistic
corr_matrix <- matrix(c(1, 0.65, 0.65, 1), nrow=2)
library(MASS)
scores <- mvrnorm(n, mu=c(28.5, 16.3), Sigma=cov2cor(corr_matrix) * c(8.2, 9.1) %o% c(8.2, 9.1))
data$pre_BDI <- scores[,1]
data$post_BDI <- scores[,2]
# Compute difference scores (Post - Pre; negative = improvement)
data$difference <- data$post_BDI - data$pre_BDI
# === STEP 1: Check Assumptions ===
# 1. Normality of DIFFERENCES (not original scores)
shapiro.test(data$difference)
# Result: p > .05, normality of differences OK
# Q-Q plot of differences
qqnorm(data$difference, main="Q-Q Plot of Difference Scores(Post - Pre)")
qqline(data$difference)
# Histogram of differences
hist(data$difference, breaks=10, col="steelblue",
main="Distribution of Change Scores(Post - Pre BDI-II)",
xlab="Change in BDI-II(negative = improvement)")
abline(v=0, col="red", lwd=2, lty=2) # Line at no change
# 2. Outliers in differences
boxplot(data$difference, horizontal=TRUE,
main="Boxplot of Difference Scores",
xlab="Change in BDI-II(Post - Pre)")
abline(v=0, col="red", lwd=2, lty=2)
# Result: No extreme outliers
# 3. Check pairing is correct
head(data) # Verify each subject has both pre and post
sum(is.na(data$pre_BDI) | is.na(data$post_BDI)) # Should be 0
# === STEP 2: Descriptive Statistics ===
cat("=== Descriptive Statistics ===\n")
cat("Pre-treatment: M =", round(mean(data$pre_BDI), 2),
", SD =", round(sd(data$pre_BDI), 2), "\n")
cat("Post-treatment: M =", round(mean(data$post_BDI), 2),
", SD =", round(sd(data$post_BDI), 2), "\n")
cat("Mean change: M =", round(mean(data$difference), 2),
", SD =", round(sd(data$difference), 2), "\n")
cat("Correlation(pre-post): r =", round(cor(data$pre_BDI, data$post_BDI), 2), "\n")
# === STEP 3: Run Paired-samples t-test ===
t_result <- t.test(data$post_BDI, data$pre_BDI, paired=TRUE)
print(t_result)
# Alternative syntax (equivalent):
# t.test(data$difference, mu=0)
# Output:
# Paired t-test
# t = -7.83, df = 34, p-value < .001
# 95% CI: [-15.3, -9.1]
# Mean difference: -12.2 points
# === STEP 4: Effect Size ===
# Cohen's dz for paired data (uses SD of differences)
cohen_dz <- mean(data$difference) / sd(data$difference)
cat("\nCohen's dz:", round(cohen_dz, 2), "\n")
# dz = -1.32 (very large effect)
# Alternative: Cohen's d using correlation adjustment
library(effsize)
cohen.d(data$post_BDI, data$pre_BDI, paired=TRUE)
# === STEP 5: Visualize Results ===
# Profile plot (spaghetti plot)
data_long <- pivot_longer(data, cols=c(pre_BDI, post_BDI),
names_to="timepoint", values_to="BDI_score")
data_long$timepoint <- factor(data_long$timepoint,
levels=c("pre_BDI", "post_BDI"),
labels=c("Baseline", "Post-CBT"))
ggplot(data_long, aes(x=timepoint, y=BDI_score, group=subject_id)) +
geom_line(alpha=0.3, color="gray50") +
geom_point(alpha=0.3, color="gray50") +
stat_summary(aes(group=1), fun=mean, geom="line",
color="red", size=1.5) +
stat_summary(fun=mean, geom="point",
color="red", size=4, shape=18) +
labs(title="Individual Trajectories: Pre-Post CBT for Depression",
subtitle="Red line = group mean; gray lines = individuals",
x="Timepoint", y="BDI-II Depression Score(0-63)") +
theme_classic()
# Paired boxplot
ggplot(data_long, aes(x=timepoint, y=BDI_score, fill=timepoint)) +
geom_boxplot(alpha=0.6) +
geom_line(aes(group=subject_id), alpha=0.2) +
labs(title="Pre-Post Depression Scores(Paired)",
x="Timepoint", y="BDI-II Depression Score") +
scale_fill_brewer(palette="Set2") +
theme_classic() +
theme(legend.position="none")
# === APA-Style Reporting ===
cat("\n=== APA-Style Report ===\n")
cat("A paired-samples t-test was conducted to evaluate the effectiveness of\n")
cat("12-week CBT for reducing depression symptoms. The difference scores were\n")
cat("approximately normally distributed(Shapiro-Wilk p > .05). There was a\n")
cat("significant reduction in BDI-II scores from baseline(M = 28.5, SD = 8.2)\n")
cat("to post-treatment(M = 16.3, SD = 9.1), t(34) = -7.83, p < .001,\n")
cat("dz = -1.32 (95% CI [-15.3, -9.1]). Participants showed an average\n")
cat("improvement of 12.2 points on the BDI-II, representing a very large effect\n")
cat("and clinically significant reduction in depression symptoms.\n")t(34) = -7.83, p < .001, dz = -1.32 (very large effect), 95% CI [-15.3, -9.1]. Participants showed significant improvement in depression (mean reduction = 12.2 points on BDI-II). The within-subject correlation (r=.65) demonstrates strong pairing, justifying paired t-test over independent t-test. Effect size consistent with Hofmann et al. (2012) meta-analysis showing CBT produces large effects for depression.
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Wilcoxon Signed-Rank Test — The robust rank-based equivalent for non-normal paired distributions.
- Bootstrap Delta Strike — Generate significance using resampled difference scores.
- Trimmed Paired T-Test — Remove the top and bottom 5% of participants with 'Impossible' recovery scores.
- Sign Test — Use purely directional math (Success/Failure) if magnitude is contaminated.
- Independent T-Test — If pre and post are unrelated, the paired advantage is lost—pivot to group comparison.
Post-hoc
Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.
- Compare with Wilcoxon signed-rank test (nonparametric alternative)
- Bootstrap confidence intervals for mean difference
- Examine normality of difference scores
- Check for carryover effects if applicable
- Calculate Cohen's dz effect size: dz = mean_diff / SD_diff
Paired t-test compares 2 related conditions. Post-hoc tests are not applicable (use repeated measures ANOVA + post-hoc for 3+ conditions).
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
Standardized mean difference for paired data, using SD of difference scores. Small: 0.2, Medium: 0.5, Large: 0.8. Formula: dz = MD / SDD where MD = mean of differences, SDD = SD of differences. Most appropriate for paired designs
Repeated measures Cohen's d, accounting for correlation between measurements. drm = MD / √(SD₁² + SD₂² - 2r×SD₁×SD₂) where r = correlation. More comparable to independent samples d
Unstandardized mean change (M_post - M_pre) with 95% CI. Easiest to interpret in original units (e.g., '12.2 point reduction on BDI-II')
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
The 'Difference Stability' Minimum: A minimum of 15 pairs is required to ensure the distribution of 'Change Scores' reaches statistical authority.
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | d=0.20 (Small) | n ≈ 199 pairs |
| Medium Effect | d=0.50 (Medium) | n ≈ 34 pairs |
| Large Effect | d=0.80 (Large) | n ≈ 15 pairs |
The 'Delta' Audit: Power is driven by the consistency of the change. If some participants recover while others decline, the variance of the differences (SD_diff) will explode, requiring a much larger N.
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
A paired-samples t-test was conducted to brief description of purpose, e.g., 'evaluate the effectiveness of 12-week CBT for reducing depression'. If assumptions checked, state: 'The difference scores were approximately normally distributed (Shapiro-Wilk p > .05).' If violated: 'Due to non-normal differences (Shapiro-Wilk p < .05), Wilcoxon signed-rank test was used as a sensitivity analysis.' There was a significant/non-significant increase/reduction/change in DV from Time1/Condition1 (M = XX.X, SD = X.X) to Time2/Condition2 (M = XX.X, SD = X.X), t(df) = X.XX, p = .XXX, dz = X.XX (95% CI X.X, X.X). Interpret effect size and practical significance in context.
- t-statistic
- degrees of freedom (n - 1)
- p-value (exact if p > .001, otherwise p < .001)
- effect size (Cohen's dz)
- 95% confidence interval for mean difference
- descriptive statistics at both timepoints (M, SD, n)
- mean and SD of difference scores
- statement about normality of differences
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Comparison | M_diff | SD_diff | t | df | p | dz (Effect Size) |
|---|---|---|---|---|---|---|
| Post - Pre | 12.4 | 4.2 | 8.54 | 59 | < .001 | 1.10 |
The Average Gain. The mean increase (or decrease) observed within the subjects.
Cohen's d for Paired Samples. Standardizes the gain relative to the variability of the change itself. dz > 1.0 indicates a massive, consistent shift.
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Execute Paired T-Test
t.test(df$post, df$pre, paired = TRUE)
# 2. Extract Paired Effect Size (Cohen's dz)
lsr::cohensD(df$post, df$pre, method = 'paired')Paired T-tests are actually OLS regressions on the 'Difference Scores'. If the differences aren't normally distributed, your p-value is a lie.
# Execute Normality Audit on Difference Scores
diff <- df$post - df$pre
shapiro.test(diff)
# Visual Check (QQ Plot)
performance::check_normality(lm(diff ~ 1))Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.