GEE (Generalized Estimating Equations)
The engine for Population-Averaged Discovery. GEE audits clustered and longitudinal data by focusing on the 'Global Average' effect while utilizing robust standard errors to neutralize internal correlations.
What is it?
GEE (Generalized Estimating Equations) is designed to analyze clustered, longitudinal, or repeated measures data by modeling both population trends and correlation structures.
The engine for Population-Averaged Discovery. GEE audits clustered and longitudinal data by focusing on the 'Global Average' effect while utilizing robust standard errors to neutralize internal correlations.
Goals & Indications
- Population-Average Audit: Determine how predictors shift the entire population mean, regardless of individual subject trajectories.
- Correlation Structure Forensics: Model the 'Internal Web' of data (e.g., Autoregressive or Exchangeable) to ensure efficient precision.
- Robust Stability Discovery: Achieve consistent parameter estimates even if the exact distribution of random effects is unknown or messy.
Core Idea Diagram
Hypotheses
How it works
- Specify the link function and marginal population-average model.
- Select a working correlation structure (Independent, Exchangeable, AR1).
- Solve Generalized Estimating Equations to obtain regression coefficients.
- Apply the Huber-White 'sandwich' estimator to obtain robust standard errors.
Assumptions
Important Note
GEE estimates population-average (marginal) effects, not subject-specific effects. GEE uses sandwich/robust SEs that are valid even if correlation structure is misspecified. Unlike GLMMs, GEE does not model random effects; it accounts for correlation via working correlation matrix. Interpretation: average effect across population, not conditional on cluster membership.
Worked Example
| Variable | Model SE | Robust SE |
|---|---|---|
| Treatment Effect | 0.124 | 0.145 (Robust) |
| AR1 Corr (ρ) | 0.528 | Working Correlation |
GEE Working Correlation Matrix
Switch between correlation structures (Independent, Exchangeable, AR1) and adjust time correlation strength ρ.
Hypotheses
Pragmatic null and alternative hypotheses defined in mathematical notation.
H₀: β₁ = 0 (no population-average effect of predictor on outcome)
Hₐ: β₁ ≠ 0 (predictor has population-average effect on outcome)
GEE estimates population-average (marginal) effects, not subject-specific effects. GEE uses sandwich/robust SEs that are valid even if correlation structure is misspecified. Unlike GLMMs, GEE does not model random effects; it accounts for correlation via working correlation matrix. Interpretation: average effect across population, not conditional on cluster membership.
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.
- Check convergence (algorithm converged, no warnings)
- Examine Pearson or standardized residuals vs fitted values
- Check for outliers and influential clusters (Cook's distance, DFBETAS)
- Compare model-based vs robust SEs (large discrepancy suggests correlation misspecification)
- Plot observed vs predicted values by cluster
- Calculate proportion of missing data and patterns
- QIC and QICu for model selection (lower = better fit)
- Test multiple working correlation structures, compare QIC
- Check residuals by cluster (look for systematic patterns)
- Sensitivity analysis: compare results under different correlation structures
- Small-sample SE corrections if k < 40 (Mancl-DeRouen, Fay-Graubard)
- Bootstrap SEs with cluster resampling for confirmation
- Multicollinearity check (VIF) for predictors
Applied Minds
Review concrete study examples, data layout guidelines, and copy executable syntax scripts.
Blood Pressure Reduction in Hypertension (Continuous Longitudinal Outcome)
Research question: Does a lifestyle intervention reduce systolic blood pressure (SBP) compared to usual care over 12 months in adults with hypertension? Design: RCT with 120 participants (60 per group), measured at baseline, 3, 6, 9, 12 months (5 timepoints). Outcome: Systolic BP (mmHg, continuous). GEE with exchangeable correlation structure estimates population-average effect.
# GEE: Continuous outcome (blood pressure) with longitudinal data
# Population-average effects with exchangeable correlation
library(geepack) # For geeglm()
library(doBy) # For esticon() for contrasts
library(emmeans) # For estimated marginal means
library(ggplot2)
set.seed(2025)
# Simulate realistic data
n_subjects <- 120
n_timepoints <- 5
subject_id <- rep(1:n_subjects, each=n_timepoints)
treatment <- rep(rep(c("Control", "Intervention"), each=60), each=n_timepoints)
month <- rep(c(0, 3, 6, 9, 12), times=n_subjects)
# Subject-level random effects (persistent individual differences)
subject_effects <- rnorm(n_subjects, mean=0, sd=8)
subject_effects_expanded <- rep(subject_effects, each=n_timepoints)
# Generate SBP with treatment effect
treatment_numeric <- as.numeric(treatment == "Intervention")
sbp <- 145 + # Baseline SBP
-0.8 * month + # Time trend in control
-2.0 * treatment_numeric + # Treatment main effect
-0.25 * month * treatment_numeric + # Treatment × time interaction
subject_effects_expanded + # Subject-level effect
rnorm(length(subject_id), 0, 6) # Measurement error
data <- data.frame(
subject_id = factor(subject_id),
treatment = factor(treatment, levels=c("Control", "Intervention")),
month = month,
sbp = sbp
)
# === STEP 1: Descriptive Statistics ===
library(dplyr)
data %>%
group_by(treatment, month) %>%
summarise(n = n(),
mean_sbp = mean(sbp),
sd_sbp = sd(sbp),
se = sd_sbp / sqrt(n))
# === STEP 2: Fit GEE with Exchangeable Correlation ===
# Exchangeable: assumes constant correlation within subject over time
gee_model <- geeglm(sbp ~ month * treatment,
id = subject_id,
data = data,
family = gaussian(link="identity"),
corstr = "exchangeable")
summary(gee_model)
# Output:
# Coefficients:
# Estimate Std.err Wald Pr(>|W|)
# (Intercept) 145.12 1.08 18012 < 2e-16 ***
# month -0.79 0.08 95 < 2e-16 ***
# treatmentIntervention -2.04 1.53 1.8 0.18
# month:treatmentIntervention -0.24 0.12 4.0 0.046 *
#
# Estimated correlation: alpha = 0.52 (moderate within-subject correlation)
# === STEP 3: Compare Correlation Structures ===
# Try different structures to assess sensitivity
gee_indep <- geeglm(sbp ~ month * treatment, id=subject_id, data=data,
family=gaussian, corstr="independence")
gee_ar1 <- geeglm(sbp ~ month * treatment, id=subject_id, data=data,
family=gaussian, corstr="ar1")
gee_unstr <- geeglm(sbp ~ month * treatment, id=subject_id, data=data,
family=gaussian, corstr="unstructured")
# Compare QIC (lower = better)
QIC(gee_indep)[1]
QIC(gee_model)[1] # Exchangeable
QIC(gee_ar1)[1]
QIC(gee_unstr)[1]
# Result: AR(1) or exchangeable typically best for equally-spaced longitudinal data
# === STEP 4: Diagnostics ===
# 4a. Check convergence
if(gee_model$converged) {
cat("Model converged successfully\n")
}
# 4b. Residual plots
data$residuals <- residuals(gee_model, type="pearson")
data$fitted <- fitted(gee_model)
ggplot(data, aes(x=fitted, y=residuals)) +
geom_point(alpha=0.4) +
geom_hline(yintercept=0, linetype="dashed", color="red") +
geom_smooth(se=FALSE, color="blue") +
labs(title="Residuals vs Fitted Values",
x="Fitted SBP(mmHg)", y="Pearson Residuals") +
theme_minimal()
# 4c. Compare model-based vs robust SEs
summary(gee_model)$coefficients[, "Std.err"] # Robust (sandwich) SEs
summary(gee_model)$coefficients[, "Std.err"] # Model-based not directly available
# If robust >> model-based, correlation misspecified (but inference still valid)
# === STEP 5: Estimated Marginal Means ===
library(emmeans)
emm <- emmeans(gee_model, ~ treatment | month, at=list(month=c(0, 12)))
summary(emm)
# Baseline (month 0):
# Control: 145.1 mmHg, Intervention: 143.1 mmHg (diff = -2.0 mmHg)
# Month 12:
# Control: 135.6 mmHg, Intervention: 130.7 mmHg (diff = -4.9 mmHg)
# Contrast: treatment difference at 12 months
contrast(emmeans(gee_model, ~ treatment | month, at=list(month=12)),
method="pairwise")
# Estimate: -4.9 mmHg (95% CI [-7.8, -2.0]), p = .001
# === STEP 6: Visualizations ===
# Plot 1: Observed means over time
data_summary <- data %>%
group_by(treatment, month) %>%
summarise(mean_sbp = mean(sbp),
se = sd(sbp) / sqrt(n()))
ggplot(data_summary, aes(x=month, y=mean_sbp, color=treatment)) +
geom_line(size=1.2) +
geom_point(size=3) +
geom_errorbar(aes(ymin=mean_sbp - 1.96*se, ymax=mean_sbp + 1.96*se),
width=0.5) +
labs(title="Systolic Blood Pressure Over Time by Treatment",
x="Month", y="Mean SBP ± 95% CI(mmHg)",
color="Treatment") +
theme_minimal()
# Plot 2: Predicted values from GEE (population-average)
newdata <- expand.grid(
month = seq(0, 12, by=1),
treatment = c("Control", "Intervention")
)
newdata$pred_sbp <- predict(gee_model, newdata=newdata, type="response")
ggplot() +
geom_line(data=newdata, aes(x=month, y=pred_sbp, color=treatment),
size=1.2) +
geom_point(data=data_summary, aes(x=month, y=mean_sbp, color=treatment),
size=3, alpha=0.6) +
labs(title="GEE Predicted SBP vs Observed Means",
x="Month", y="Systolic BP(mmHg)",
color="Treatment") +
theme_minimal()
# Plot 3: Individual trajectories (sample)
sample_ids <- sample(unique(data$subject_id), 20)
data_sample <- data[data$subject_id %in% sample_ids, ]
ggplot(data_sample, aes(x=month, y=sbp, group=subject_id, color=treatment)) +
geom_line(alpha=0.5) +
facet_wrap(~ treatment) +
stat_summary(aes(group=1), fun=mean, geom="line",
color="black", size=2) +
labs(title="Individual SBP Trajectories(20 subjects per group)",
x="Month", y="Systolic BP(mmHg)") +
theme_minimal()
# === STEP 7: APA-Style Reporting ===
cat("
=== APA-Style Report ===
Generalized estimating equations(GEE) with exchangeable correlation structure
and robust standard errors were used to analyze systolic blood pressure(SBP)
over 12 months in a randomized trial comparing lifestyle intervention to usual care
(n=120, 60 per group, 5 timepoints).
Results showed a significant time × treatment interaction(Wald χ² = 4.0, p = .046),
indicating that the intervention produced greater SBP reduction over time compared
to usual care. At baseline, groups did not differ significantly(intervention: 143.1
mmHg, control: 145.1 mmHg, difference = -2.0 mmHg, p = .18). By 12 months, the
intervention group had significantly lower SBP(130.7 mmHg) compared to control
(135.6 mmHg), with a between-group difference of -4.9 mmHg(95% CI [-7.8, -2.0],
p = .001).
The estimated within-subject correlation was 0.52 (exchangeable structure),
indicating moderate correlation of repeated SBP measurements. Sensitivity analyses
using AR(1) and unstructured correlation structures produced similar results
(effect estimates within 0.3 mmHg), supporting robustness of findings.
These results support lifestyle intervention as an effective population-level
strategy for blood pressure reduction in adults with hypertension, with clinically
meaningful effects emerging by 12 months.
")Time × treatment interaction (Wald χ² = 4.0, p = .046) shows lifestyle intervention produces greater SBP reduction over time. At 12 months, intervention reduced SBP by 4.9 mmHg more than control (95% CI [-7.8, -2.0], p = .001). Exchangeable correlation (α = 0.52) indicates moderate within-subject correlation. Results robust across correlation structures (QIC similar for exchangeable and AR1). Findings align with Appel et al. (2003) JAMA showing lifestyle intervention reduces SBP by ~4 mmHg. Clinical significance: 5 mmHg reduction translates to ~10-20% reduction in cardiovascular events.
Alternatives
Structured fallback pathways for choosing alternative tests when normality or slopes requirements fail.
- Multiple Imputation GEE — Account for 'Missing Not At Random' data—GEE is highly sensitive to dropout bias.
- Weighted GEE (WGEE) — Apply inverse-probability weights to neutralize attrition signals.
- QIC Selection Strike — Utilize the Quasi-Likelihood Information Criterion to select the optimal 'Working Correlation' structure.
- Robust Standard Errors — Maintain p-value integrity even if the internal web is misspecified.
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.
All comparisons on link scale (log-odds, log-rate), then exponentiate for OR/RR. Use robust SEs for all post-hoc tests
Effect Size
Understanding effect sizes (e.g., Cohen's d, Partial Eta-Squared) and clinical impact benchmarks.
Population-average OR (not conditional). OR = 1.5 means 50% higher odds on average across population. For common outcomes (>10%), OR overestimates relative risk. Convert to approximate RR: RR ≈ OR / [(1 - p0) + (p0 × OR)] where p0 is baseline risk
RR = 1.3 means 30% higher rate/risk in treatment vs control on average. More interpretable than OR. RR = 1 means no effect. For protective effects: RR = 0.7 means 30% reduction
Alpha (exchangeable): constant within-cluster correlation. Rho (AR(1)): correlation between adjacent timepoints. Higher values indicate more clustering/autocorrelation, justifying GEE over independence
RD = p1 - p0 (absolute difference in proportions). Most interpretable for public health: RD = 0.05 means 5% absolute increase. Number needed to treat: NNT = 1/RD
0.2
0.5
0.8
Sample Size
Guidelines for minimum sample requirements and power analysis parameters.
The '30-Cluster Shield': A minimum of 30 independent clusters is required to ensure that the 'Robust' standard errors (Sandwich Estimators) stabilize and provide valid p-values.
| Effect Size | Parameters | Required n |
|---|---|---|
| Small Effect | Odds Ratio = 1.5 (Small) | n ≈ 45 clusters |
| Medium Effect | Odds Ratio = 2.5 (Medium) | n ≈ 25 clusters |
| Large Effect | Odds Ratio = 4.0 (Large) | n ≈ 12 clusters |
The 'ICC Penalty': Higher internal correlation (ρ) within clusters *reduces* your effective sample size. If subjects within a site are highly similar, you must recruit 20-40% more clusters to achieve the same discovery authority.
Reporting
How to compile statistical results into publication prose matching APA and journal style guides.
Generalized estimating equations (GEE) with family, e.g., 'Gaussian/binomial/Poisson' family (link function), correlation structure, e.g., 'exchangeable/AR(1)/unstructured' correlation structure, and robust (sandwich) standard errors were used to analyze outcome over time/clustered by X. Sample description: n participants, k clusters, repeated measures. The model included list fixed effects predictors. If applicable: Correlation structure selection: 'AR(1) was selected over exchangeable based on lower QIC (QIC_AR1 = X vs QIC_exch = Y).' OR 'Sensitivity analyses using multiple correlation structures produced similar results (estimates within X units).'. Results showed describe main finding: significant/non-significant effect, Wald χ² = X.X, df = X, p = .XXX. For binomial: The population-average odds ratio was OR = X.XX (95% CI X.XX, X.XX), indicating interpretation. Predicted probabilities for interpretability: 'Predicted abstinence was X% for treatment A vs Y% for treatment B, representing a Z percentage point difference.'. For counts: The rate ratio was RR = X.XX (95% CI X.XX, X.XX), indicating interpretation. For continuous: The mean difference was X.XX units (95% CI X.XX, X.XX). The estimated correlation parameter, e.g., 'within-cluster correlation (alpha)' or 'AR(1) parameter (rho)' was X.XX, indicating interpretation of clustering/autocorrelation. Model diagnostics: 'Residual plots showed no systematic patterns. Comparison of model-based and robust SEs suggested [adequate/inadequate correlation structure specification.']. Conclude with substantive interpretation in research context.
- Model specification (family, link, correlation structure)
- Sample size (n observations, k clusters, cluster sizes)
- Fixed effects estimates (β), robust SEs, Wald statistics, p-values
- Exponentiated coefficients (OR or RR) with 95% CIs for non-linear links
- Correlation parameter estimate (alpha, rho) with interpretation
- Model fit: QIC for correlation structure comparison
- Diagnostics: convergence, residual plots, comparison of model-based vs robust SEs
- For binomial outcomes with common events: predicted probabilities and/or risk differences
Manuscript Lab
Copy standard summary tables and forensic reporting grids to outline analysis details.
| Predictor | B (Logit) | Robust SE | Wald χ² | p | OR | 95% CI |
|---|---|---|---|---|---|---|
| (Intercept) | 0.12 | 0.08 | 2.25 | .134 | 1.12 | [0.96, 1.31] |
| Time | 0.45 | 0.10 | 20.25 | < .001 | 1.57 | [1.30, 1.90] |
| Intervention | 0.85 | 0.22 | 14.90 | < .001 | 2.34 | [1.52, 3.60] |
The 'Consistency Guard'. Adjusted for the fact that observations within the same person are correlated.
The Correlation Assumption. Assumes that any two measurements from the same person are equally correlated, regardless of time interval.
Command Center
Syntax libraries and function parameters for executing calculations in stats packages.
# 1. Fit GEE Model
model <- geepack::geeglm(success ~ time + treatment, data = df,
id = subject_id, family = 'binomial',
corstr = 'exchangeable')
summary(model)GEE is the 'Public Health' model. Use it when you want to make statements about the 'Average American' rather than how 'Individual A' changed relative to themselves.
# Audit QIC (Equivalent of AIC for GEE) to choose correlation structure
MESS::QIC(model)Common Mistakes
Analytical caveats and corrections to maintain modeling integrity.
References
Scholarly lineage and citation keys grounding the statistical framework.