| name | causal-mediation |
| description | Causal mediation analysis in R, including direct and indirect effects, assumptions, and sensitivity analysis. |
Causal Mediation Analysis in R
Overview
Causal mediation analysis methods for decomposing total effects into direct and indirect effects. Covers traditional approaches, natural effect models, sensitivity analysis for unmeasured confounding, mediation with survival outcomes, and comprehensive causal mediation frameworks.
Traditional Mediation (Baron-Kenny)
Basic Approach
fit_total <- lm(outcome ~ treatment + covariates, data = df)
c_total <- coef(fit_total)["treatment"]
fit_med <- lm(mediator ~ treatment + covariates, data = df)
a <- coef(fit_med)["treatment"]
fit_direct <- lm(outcome ~ treatment + mediator + covariates, data = df)
c_prime <- coef(fit_direct)["treatment"]
b <- coef(fit_direct)["mediator"]
indirect_effect <- a * b
direct_effect <- c_prime
total_effect <- c_total
proportion_mediated <- indirect_effect / total_effect
cat("Total effect:", round(total_effect, 4), "\n")
cat("Direct effect:", round(direct_effect, 4), "\n")
cat("Indirect effect:", round(indirect_effect, 4), "\n")
cat("Proportion mediated:", round(proportion_mediated * 100, 1), "%\n")
Sobel Test (Not Recommended for Small Samples)
sobel_test <- function(a, b, se_a, se_b) {
se_ab <- sqrt(b^2 * se_a^2 + a^2 * se_b^2)
z <- (a * b) / se_ab
p <- 2 * pnorm(-abs(z))
return(list(indirect = a * b, se = se_ab, z = z, p = p))
}
se_a <- summary(fit_med)$coefficients["treatment", "Std. Error"]
se_b <- summary(fit_direct)$coefficients["mediator", "Std. Error"]
sobel <- sobel_test(a, b, se_a, se_b)
print(sobel)
Causal Mediation with mediation Package
Basic Mediation Analysis
library(mediation)
med_model <- lm(mediator ~ treatment + age + sex, data = df)
out_model <- lm(outcome ~ treatment + mediator + age + sex, data = df)
med_result <- mediate(
med_model,
out_model,
treat = "treatment",
mediator = "mediator",
boot = TRUE,
boot.ci.type = "bca",
sims = 1000
)
summary(med_result)
plot(med_result)
Binary Outcomes
library(mediation)
med_model <- lm(mediator ~ treatment + covariates, data = df)
out_model <- glm(outcome ~ treatment + mediator + covariates,
family = binomial(link = "logit"), data = df)
med_result <- mediate(
med_model,
out_model,
treat = "treatment",
mediator = "mediator",
boot = TRUE,
sims = 1000
)
summary(med_result)
Binary Mediator
library(mediation)
med_model <- glm(mediator ~ treatment + covariates,
family = binomial, data = df)
out_model <- lm(outcome ~ treatment + mediator + covariates, data = df)
med_result <- mediate(
med_model,
out_model,
treat = "treatment",
mediator = "mediator",
boot = TRUE,
sims = 1000
)
summary(med_result)
Treatment-Mediator Interaction
library(mediation)
out_model <- lm(outcome ~ treatment * mediator + covariates, data = df)
med_result <- mediate(
med_model,
out_model,
treat = "treatment",
mediator = "mediator",
boot = TRUE,
sims = 1000
)
summary(med_result)
Natural Effect Models with medflex
Imputation-Based Approach
library(medflex)
expData <- neWeight(
outcome ~ treatment + mediator + age + sex,
data = df
)
neMod <- neModel(
outcome ~ treatment0 + treatment1 + age + sex,
expData = expData,
se = "robust"
)
neEffdecomp(neMod)
Weighting-Based Approach
library(medflex)
expData <- neWeight(
outcome ~ treatment + mediator + age + sex,
data = df,
weights = "estimated"
)
neMod <- neModel(
outcome ~ treatment0 + treatment1 + age + sex,
expData = expData,
se = "bootstrap",
nBoot = 1000
)
summary(neMod)
neEffdecomp(neMod)
Comprehensive Mediation with CMAverse
Basic CMAverse Analysis
library(CMAverse)
cma_result <- cmest(
data = df,
outcome = "outcome",
exposure = "treatment",
mediator = "mediator",
basec = c("age", "sex", "baseline"),
EMint = TRUE,
model = "rb",
estimation = "imputation",
inference = "bootstrap",
nboot = 1000
)
summary(cma_result)
Multiple Mediators
library(CMAverse)
cma_multi <- cmest(
data = df,
outcome = "outcome",
exposure = "treatment",
mediator = c("mediator1", "mediator2"),
basec = c("age", "sex"),
EMint = TRUE,
model = "rb",
estimation = "imputation",
inference = "bootstrap",
nboot = 500
)
summary(cma_multi)
Sequential Mediators
library(CMAverse)
cma_seq <- cmest(
data = df,
outcome = "outcome",
exposure = "treatment",
mediator = c("mediator1", "mediator2"),
basec = c("age", "sex"),
EMint = TRUE,
model = "rb",
mreg = list("linear", "linear"),
yreg = "linear",
estimation = "imputation",
inference = "bootstrap",
nboot = 500
)
summary(cma_seq)
Mediation with Survival Outcomes
Using mediation Package
library(mediation)
library(survival)
med_model <- lm(mediator ~ treatment + age + sex, data = df)
surv_model <- coxph(Surv(time, event) ~ treatment + mediator + age + sex,
data = df)
med_surv <- mediate(
med_model,
surv_model,
treat = "treatment",
mediator = "mediator",
sims = 1000
)
summary(med_surv)
Survival Mediation with CMAverse
library(CMAverse)
cma_surv <- cmest(
data = df,
outcome = "event",
event = "event",
eventtime = "time",
exposure = "treatment",
mediator = "mediator",
basec = c("age", "sex"),
EMint = TRUE,
model = "rb",
yreg = "coxph",
estimation = "paramfunc",
inference = "bootstrap",
nboot = 500
)
summary(cma_surv)
Sensitivity Analysis
Sensitivity to Unmeasured Confounding
library(mediation)
sens_result <- medsens(
med_result,
rho.by = 0.05,
effect.type = "indirect",
sims = 1000
)
summary(sens_result)
plot(sens_result)
E-value for Mediation
library(EValue)
nie_estimate <- med_result$d0
nie_se <- med_result$d0.se
nie_ci_lower <- med_result$d0.ci[1]
Sensitivity in CMAverse
library(CMAverse)
cma_sens <- cmsens(
object = cma_result,
sens = "uc",
eval_uc = list(
ume_effect = seq(-0.5, 0.5, 0.1),
uye_effect = seq(-0.5, 0.5, 0.1)
)
)
summary(cma_sens)
plot(cma_sens)
Moderated Mediation
Conditional Process Analysis
library(mediation)
out_model_mod <- lm(outcome ~ treatment * moderator + mediator + covariates,
data = df)
med_low <- mediate(
med_model,
out_model_mod,
treat = "treatment",
mediator = "mediator",
covariates = list(moderator = quantile(df$moderator, 0.25)),
boot = TRUE,
sims = 500
)
med_high <- mediate(
med_model,
out_model_mod,
treat = "treatment",
mediator = "mediator",
covariates = list(moderator = quantile(df$moderator, 0.75)),
boot = TRUE,
sims = 500
)
summary(med_low)
summary(med_high)
test.modmed(med_result, list(moderator = "low"), list(moderator = "high"))
Causal Diagrams for Mediation
library(dagitty)
library(ggdag)
dag_mediation <- dagitty('
dag {
X -> M
M -> Y
X -> Y
C -> X
C -> M
C -> Y
}
')
adjustmentSets(dag_mediation, exposure = "X", outcome = "Y")
ggdag(dag_mediation) +
theme_dag() +
labs(title = "Mediation DAG")
Reporting Mediation Results
create_mediation_table <- function(med_result) {
effects <- data.frame(
Effect = c("ACME (Indirect)", "ADE (Direct)", "Total Effect",
"Proportion Mediated"),
Estimate = c(med_result$d0, med_result$z0, med_result$tau.coef,
med_result$n0),
CI_Lower = c(med_result$d0.ci[1], med_result$z0.ci[1],
med_result$tau.ci[1], med_result$n0.ci[1]),
CI_Upper = c(med_result$d0.ci[2], med_result$z0.ci[2],
med_result$tau.ci[2], med_result$n0.ci[2]),
P_value = c(med_result$d0.p, med_result$z0.p,
med_result$tau.p, med_result$n0.p)
)
effects <- effects |>
mutate(across(c(Estimate, CI_Lower, CI_Upper), ~round(., 4))) |>
mutate(P_value = format.pval(P_value, digits = 3))
return(effects)
}
med_table <- create_mediation_table(med_result)
print(med_table)
Key Packages Summary
| Package | Purpose |
|---|
| mediation | Causal mediation analysis |
| medflex | Natural effect models |
| CMAverse | Comprehensive causal mediation |
| intmed | Interventional effects |
| sensmediation | Sensitivity analysis |
| mediator | SEM-based mediation |
| lavaan | Structural equation modeling |
| dagitty | Causal DAG analysis |
Best Practices
- Causal assumptions: Clearly state and justify no unmeasured confounding
- DAGs: Draw and analyze causal diagram before analysis
- Bootstrap: Use bootstrap CIs instead of Sobel test
- Sensitivity: Always conduct sensitivity analysis for unmeasured confounding
- Interactions: Test for exposure-mediator interaction
- Multiple mediators: Use appropriate methods for parallel vs sequential
- Reporting: Report all effects (direct, indirect, total) with CIs
- Interpretation: Consider biological/theoretical plausibility of mechanism