Three-way Repeated Measures ANOVA
Analyze three within-subjects factors (all repeated measures) on a continuous outcome..
What is it?
Three-Way Repeated Measures ANOVA assesses the impact of three within-subjects factors (e.g., Dose, Time, and Task Type) on a continuous dependent variable.
When to use it
- 3 Within Factors: Every subject completes all combinations (e.g. 3 Doses x 2 Times x 2 Tasks).
- Outcome: Continuous outcome variable.
Core Idea
Isolates the 3-way synergistic effect. Shows if the combined effect of Dose and Time varies depending on the Task performed:
This design has the absolute highest statistical power per participant, but suffers from severe fatigue and learning effect threats.
Hypotheses
Tests 7 separate hypotheses: 3 main effects, 3 two-way interactions, and 1 three-way interaction.
How it works
The total within-subject variance is partitioned into 7 effects, each tested against its own individual interaction-with-subjects error term.
Assumptions
Important Note
If sphericity fails repeatedly, a multivariate (MANOVA) approach or linear mixed modeling (LMM) is strongly recommended.
Quick Example
Three-Way RM ANOVA Live Laboratory
Vary the three within-subjects factors to observe the complex 3-way repeated measures output.
| Source | SS | F | p-value |
|---|---|---|---|
| Factor A (Dose) | 300.0 | 4.69 | p < 0.05 |
| Factor B (Time) | 300.0 | 4.69 | p < 0.05 |
| Factor C (Task) | 0.0 | 0.00 | p > 0.05 |
| ABC Interaction | 0.0 | 0.00 | p > 0.05 |
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: No main effects or interactions exist for any of the three within-subjects factors (all condition means are equal after controlling for individual differences)
Hₐ: At least one main effect or interaction exists among the three within-subjects factors
Tests main effects for Factor A, B, and C, plus all two-way interactions (A×B, A×C, B×C) and the three-way interaction (A×B×C). Each test requires sphericity assumption. With 3 factors of 3 levels each, you're testing 7 effects across 27 repeated measurements per subject.
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.
- Mauchly's test of sphericity for all main effects and interactions (7 tests total)
- Greenhouse-Geisser or Huynh-Feldt epsilon (ε) for degree of sphericity violation
- Descriptive statistics (M, SD) for all conditions
- Profile plots (interaction plots) for all two-way and three-way interactions
- Q-Q plots of residuals or key difference scores
- Shapiro-Wilk test on difference scores for main contrasts
- Check for missing data patterns and % missing per condition
- Residual plots to detect outliers or heteroscedasticity
- Counterbalancing verification (order × condition interaction)
- Simple effects analysis for significant interactions
- Effect size (partial η²) for all significant effects
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Mindfulness Training and Cognitive Performance Across Tasks, Time, and Difficulty
Research question: Does mindfulness meditation training improve cognitive performance across multiple task types, time points, and difficulty levels? Design: 20 participants complete attention tasks under 3×3×3 fully within-subjects design: Task Type (Stroop, Flanker, Go/No-Go) × Time (Pre-training, Mid-training [4 weeks], Post-training [8 weeks]) × Difficulty (Easy, Medium, Hard). Each participant completes all 27 conditions in randomized order across multiple sessions. Outcome: Response accuracy (% correct, continuous 0-100).
# Three-way Repeated Measures ANOVA: Mindfulness × Task × Time × Difficulty
# Fully within-subjects design (3×3×3 = 27 conditions per participant)
# Load packages
library(tidyverse) # Data manipulation and visualization
library(ez) # For ezANOVA (simplified RM-ANOVA)
library(rstatix) # For anova_test and effect sizes
library(emmeans) # For post-hoc contrasts and simple effects
library(afex) # Alternative: aov_ez for RM-ANOVA
# Set seed for reproducibility
set.seed(2025)
# Simulate realistic data (or load: data <- read.csv("mindfulness_cognition.csv"))
# Effect pattern: Time effect (improvement), Difficulty effect (harder = worse),
# Time × Difficulty interaction (more improvement on hard tasks)
n_subjects <- 20
data <- expand.grid(
subject = factor(1:n_subjects),
task = factor(c("Stroop", "Flanker", "GoNoGo")),
time = factor(c("Pre", "Mid", "Post"), levels=c("Pre", "Mid", "Post")),
difficulty = factor(c("Easy", "Medium", "Hard"), levels=c("Easy", "Medium", "Hard"))
)
# Generate accuracy with realistic effects
data <- data %>%
mutate(
# Base accuracy by difficulty
base_acc = case_when(
difficulty == "Easy" ~ 85,
difficulty == "Medium" ~ 75,
difficulty == "Hard" ~ 60
),
# Time effect (training improvement)
time_effect = case_when(
time == "Pre" ~ 0,
time == "Mid" ~ 3,
time == "Post" ~ 6
),
# Time × Difficulty interaction (more improvement on hard tasks)
interaction_effect = case_when(
time == "Pre" ~ 0,
time == "Mid" & difficulty == "Hard" ~ 2,
time == "Post" & difficulty == "Hard" ~ 5,
TRUE ~ 0
),
# Subject random effect (individual differences)
subject_effect = as.numeric(subject) * 0.5 - 5,
# Generate accuracy
accuracy = base_acc + time_effect + interaction_effect + subject_effect + rnorm(n(), 0, 4)
) %>%
select(subject, task, time, difficulty, accuracy)
# Ensure accuracy is bounded [0, 100]
data$accuracy <- pmin(pmax(data$accuracy, 0), 100)
cat("=== Data Structure ===", "\n")
cat("Total observations:", nrow(data), "\n")
cat("Observations per subject:", nrow(data) / n_subjects, "\n")
cat("Design: 3 tasks × 3 time points × 3 difficulty levels = 27 conditions\n\n")
# === STEP 1: Check Assumptions ===
# 1. Check for missing data
missing_count <- sum(is.na(data$accuracy))
cat("Missing observations:", missing_count, "\n\n")
# 2. Descriptive statistics
cat("=== Descriptive Statistics ===", "\n")
desc_stats <- data %>%
group_by(task, time, difficulty) %>%
summarise(
n = n(),
M = mean(accuracy),
SD = sd(accuracy),
.groups = "drop"
)
print(desc_stats, n=27)
# === STEP 2: Run Three-way RM-ANOVA ===
# Method 1: Using ez::ezANOVA (comprehensive output with sphericity tests)
cat("\n=== Three-way RM-ANOVA(ezANOVA) ===", "\n")
anova_result <- ezANOVA(
data = data,
dv = accuracy,
wid = subject,
within = .(task, time, difficulty),
detailed = TRUE,
type = 3
)
print(anova_result)
# Extract ANOVA table
anova_table <- anova_result$ANOVA
cat("\n=== Main Effects and Interactions ===", "\n")
print(anova_table)
# Extract sphericity tests
if(!is.null(anova_result$`Mauchly's Test for Sphericity`)) {
cat("\n=== Mauchly's Test for Sphericity ===", "\n")
print(anova_result$`Mauchly's Test for Sphericity`)
cat("\nInterpretation: p < .05 indicates sphericity violated(use GG or HF correction)\n")
}
# Extract sphericity corrections
if(!is.null(anova_result$`Sphericity Corrections`)) {
cat("\n=== Sphericity Corrections ===", "\n")
print(anova_result$`Sphericity Corrections`)
cat("\nGG = Greenhouse-Geisser(conservative), HF = Huynh-Feldt(less conservative)\n")
cat("Use GG if epsilon < .75, use HF if epsilon > .75\n")
}
# Method 2: Using rstatix::anova_test (alternative)
cat("\n=== Alternative: rstatix anova_test ===", "\n")
anova_rstatix <- anova_test(
data = data,
dv = accuracy,
wid = subject,
within = c(task, time, difficulty),
effect.size = "ges" # Generalized eta squared
)
print(get_anova_table(anova_rstatix))
# === STEP 3: Check Normality of Residuals ===
# Compute residuals (within-subject deviations)
data <- data %>%
group_by(subject) %>%
mutate(residual = accuracy - mean(accuracy)) %>%
ungroup()
# Q-Q plot
cat("\n=== Normality Check ===", "\n")
par(mfrow=c(1,2))
qqnorm(data$residual, main="Q-Q Plot of Residuals")
qqline(data$residual, col="red")
hist(data$residual, breaks=30, main="Histogram of Residuals", xlab="Residual")
# Shapiro-Wilk test
shapiro_test <- shapiro.test(sample(data$residual, min(5000, length(data$residual))))
cat("Shapiro-Wilk test: W =", round(shapiro_test$statistic, 3),
", p =", round(shapiro_test$p.value, 4), "\n")
cat(ifelse(shapiro_test$p.value > .05, "✓ Normality OK", "⚠ Normality violated"), "\n\n")
# === STEP 4: Visualize Interactions ===
# Two-way interaction: Time × Difficulty
cat("=== Visualizing Interactions ===", "\n")
time_diff_means <- data %>%
group_by(time, difficulty) %>%
summarise(M = mean(accuracy), SE = sd(accuracy)/sqrt(n()), .groups="drop")
p1 <- ggplot(time_diff_means, aes(x=time, y=M, color=difficulty, group=difficulty)) +
geom_line(linewidth=1.2) +
geom_point(size=3) +
geom_errorbar(aes(ymin=M-SE, ymax=M+SE), width=0.1) +
labs(title="Time × Difficulty Interaction",
subtitle="Training improves accuracy more for hard tasks",
x="Time Point", y="Accuracy(% correct) ± SE",
color="Difficulty") +
theme_classic() +
theme(legend.position="right")
print(p1)
# Three-way interaction: Task × Time × Difficulty (faceted)
task_time_diff_means <- data %>%
group_by(task, time, difficulty) %>%
summarise(M = mean(accuracy), SE = sd(accuracy)/sqrt(n()), .groups="drop")
p2 <- ggplot(task_time_diff_means, aes(x=time, y=M, color=difficulty, group=difficulty)) +
geom_line(linewidth=1) +
geom_point(size=2.5) +
facet_wrap(~task, nrow=1) +
labs(title="Three-way Interaction: Task × Time × Difficulty",
x="Time Point", y="Accuracy(% correct)",
color="Difficulty") +
theme_bw() +
theme(legend.position="bottom")
print(p2)
# === STEP 5: Post-hoc Tests and Simple Effects ===
# If Time × Difficulty interaction significant, decompose with simple effects
cat("\n=== Simple Effects: Effect of Time at each Difficulty Level ===", "\n")
# Test effect of Time separately for each Difficulty level
for(diff_level in c("Easy", "Medium", "Hard")) {
cat("\n--- Difficulty:", diff_level, "---\n")
subset_data <- data %>% filter(difficulty == diff_level)
simple_anova <- anova_test(
data = subset_data,
dv = accuracy,
wid = subject,
within = time
)
print(get_anova_table(simple_anova))
}
# Pairwise comparisons for Time (collapsed across Task and Difficulty)
cat("\n=== Pairwise Comparisons: Time(Main Effect) ===", "\n")
pairwise_time <- data %>%
pairwise_t_test(
accuracy ~ time,
paired = TRUE,
p.adjust.method = "bonferroni"
)
print(pairwise_time)
# === STEP 6: Effect Sizes ===
cat("\n=== Effect Sizes(Partial Eta Squared) ===", "\n")
cat("From ANOVA table above(ges column = generalized eta squared)\n")
cat("Interpretation: .01 = small, .06 = medium, .14 = large(Cohen, 1988)\n\n")
# === APA-Style Reporting ===
cat("\n=== APA-Style Report ===", "\n")
cat("
A three-way repeated measures ANOVA was conducted to examine the effects of
mindfulness training on cognitive task performance across task type(Stroop,
Flanker, Go/No-Go), time(Pre, Mid, Post), and difficulty(Easy, Medium, Hard).
Mauchly's test indicated sphericity was violated for the Time main effect,
χ²(2) = 8.45, p = .015, therefore Greenhouse-Geisser corrected values are reported
(ε = .82).
Results revealed significant main effects for Time, F(1.64, 31.16) = 45.23, p < .001,
η²_G = .18 (large effect), and Difficulty, F(2, 38) = 287.56, p < .001, η²_G = .72
(large effect). The Task main effect was not significant, F(2, 38) = 2.13, p = .13.
Crucially, a significant Time × Difficulty interaction emerged, F(4, 76) = 12.34,
p < .001, η²_G = .08 (medium effect). Simple effects analysis revealed that
mindfulness training improved accuracy at all difficulty levels(all p < .001),
but the improvement was larger for Hard tasks(Pre: 60% → Post: 71%, Δ = 11%)
compared to Easy tasks(Pre: 85% → Post: 91%, Δ = 6%). The three-way interaction
was not significant, F(8, 152) = 1.45, p = .18.
These findings suggest mindfulness training enhances cognitive performance with
larger benefits for more challenging tasks, consistent with executive function
improvement theories.
")
cat("\n=== Key Statistics to Report ===", "\n")
cat("• Main effect Time: F(df1, df2) = X.XX, p < .001, η²_G = .XX\n")
cat("• Main effect Difficulty: F(df1, df2) = X.XX, p < .001, η²_G = .XX\n")
cat("• Interaction Time × Difficulty: F(df1, df2) = X.XX, p < .001, η²_G = .XX\n")
cat("• Sphericity corrections applied where violated(report ε and corrected df)\n")
cat("• Include descriptive statistics(M, SD) for all conditions\n")
cat("• Report simple effects for significant interactions\n")Main effects for Time (F[2,38] = 45.23, p < .001, η²_p = .70) and Difficulty (F[2,38] = 287.56, p < .001, η²_p = .94) were significant. Critically, Time × Difficulty interaction was significant (F[4,76] = 12.34, p < .001, η²_p = .39): mindfulness training improved accuracy more for Hard tasks (Δ = 11%) than Easy tasks (Δ = 6%). This supports the theory that mindfulness preferentially enhances executive function under high cognitive load. Three-way interaction was non-significant (p = .18), indicating the Time × Difficulty pattern generalized across all task types.
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Greenhouse-Geisser Shield — Mandatory adjustment for all three factors and their interactions.
- MANOVA Profile Strike — Treat the multi-level grid as a multivariate vector to bypass sphericity.
- Bootstrap Interaction Strike — Generate robust CIs for the triple synergy term.
- Log-Transformation — Neutralize extreme skewed trajectories.
Post-hoc
Group mean comparisons and correction controls (e.g. Tukey HSD, Bonferroni) to protect against Family-Wise Error Rates.
Post-hoc pairwise tests defined for this model.
No specific guidelines provided.
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
Proportion of variance explained after removing other effects. Small: .01, Medium: .06, Large: .14 (Cohen, 1988). Most commonly reported for RM-ANOVA
Comparable across different designs (between vs within). More appropriate for mixed designs. Same thresholds as partial η²
Less biased estimate of population effect size. Use for within-subjects effects when available
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
At least 15-20 subjects for adequate power, but depends heavily on effect size and number of repeated measures
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | α=.05, power=.80 | n ≈ 84 subjects |
| Medium Effect | α=.05, power=.80 | n ≈ 18 subjects |
| Large Effect | α=.05, power=.80 | n ≈ 8 subjects |
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
A three-way repeated measures ANOVA was conducted to examine the effects of Factor A, Factor B, and Factor C on DV. Mauchly's test of sphericity was assessed for all within-subjects effects; state if violated and which correction used: Greenhouse-Geisser (ε = .XX) or Huynh-Feldt (ε = .XX). Results revealed significant main effects for list significant main effects with F(df1, df2) = X.XX, p = .XXX, η²_p = .XX. Describe significant two-way interactions. Describe three-way interaction if significant, followed by simple effects decomposition. Post-hoc pairwise comparisons using correction method indicated describe key differences with means and p-values.
- F-statistic for all main effects and interactions
- degrees of freedom (corrected if sphericity violated)
- p-values
- effect sizes (partial η² or generalized η²)
- sphericity test results and corrections applied
- descriptive statistics (M, SD) for key conditions
- simple effects analysis for significant interactions
- post-hoc pairwise comparisons with corrections
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Source | df | MS | F | p | ηp² |
|---|---|---|---|---|---|
| Condition (C) | 1 | 124.5 | 10.2 | .003 | .21 |
| Task (T) | 1 | 45.2 | 3.8 | .058 | .09 |
| Time (Ti) | 2 | 310.1 | 25.4 | < .001 | .39 |
| C × T × Ti | 2 | 65.4 | 5.12 | .008 | .12 |
| Error (C×T×Ti) | 78 | 12.8 | — | — | — |
The 'Cognitive Complexity' Audit. Does the effect of the Condition on Task Performance change over Time?
Specific Error Term. In RM-ANOVA, every interaction has its own specific error term (the interaction with the Subject ID).
Signal Strength. Ratio of the triple interaction variance to the random triple interaction noise.
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Execute 3-Way Pure RM-ANOVA
model <- aov_ez(id = 'subID', dv = 'rt', data = df,
within = c('cond', 'task', 'time'))
# 2. Visualize the Triple Interaction
emmip(model, cond ~ time | task)With three within-subject factors, Sphericity violations multiply. Always prioritize the Corrected p-values (GG or HF).
# Auto-Corrected Output (Greenhouse-Geisser)
print(model, correction = 'GG')
# Decomposition of Triple Interaction
emmeans(model, pairwise ~ cond | task + time)Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.