19.2 Causal Inference Approach to Mediation
Traditional mediation models assume that regression-based estimates provide valid causal inference. However, causal mediation analysis (CMA) extends beyond traditional models by explicitly defining mediation in terms of potential outcomes and counterfactuals.
19.2.1 Example: Traditional Mediation Analysis
We begin with a classic three-step mediation approach.
# Load data
myData <- read.csv("data/mediationData.csv")
# Step 1 (Total Effect: X → Y) [No longer required]
model.0 <- lm(Y ~ X, data = myData)
summary(model.0)
#>
#> Call:
#> lm(formula = Y ~ X, data = myData)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -5.0262 -1.2340 -0.3282 1.5583 5.1622
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 2.8572 0.6932 4.122 7.88e-05 ***
#> X 0.3961 0.1112 3.564 0.000567 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 1.929 on 98 degrees of freedom
#> Multiple R-squared: 0.1147, Adjusted R-squared: 0.1057
#> F-statistic: 12.7 on 1 and 98 DF, p-value: 0.0005671
# Step 2 (Effect of X on M)
model.M <- lm(M ~ X, data = myData)
summary(model.M)
#>
#> Call:
#> lm(formula = M ~ X, data = myData)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -4.3046 -0.8656 0.1344 1.1344 4.6954
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 1.49952 0.58920 2.545 0.0125 *
#> X 0.56102 0.09448 5.938 4.39e-08 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 1.639 on 98 degrees of freedom
#> Multiple R-squared: 0.2646, Adjusted R-squared: 0.2571
#> F-statistic: 35.26 on 1 and 98 DF, p-value: 4.391e-08
# Step 3 (Effect of M on Y, controlling for X)
model.Y <- lm(Y ~ X + M, data = myData)
summary(model.Y)
#>
#> Call:
#> lm(formula = Y ~ X + M, data = myData)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -3.7631 -1.2393 0.0308 1.0832 4.0055
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 1.9043 0.6055 3.145 0.0022 **
#> X 0.0396 0.1096 0.361 0.7187
#> M 0.6355 0.1005 6.321 7.92e-09 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 1.631 on 97 degrees of freedom
#> Multiple R-squared: 0.373, Adjusted R-squared: 0.3601
#> F-statistic: 28.85 on 2 and 97 DF, p-value: 1.471e-10
# Step 4: Bootstrapping for ACME
library(mediation)
results <-
mediate(
model.M,
model.Y,
treat = 'X',
mediator = 'M',
boot = TRUE,
sims = 500
)
summary(results)
#>
#> Causal Mediation Analysis
#>
#> Nonparametric Bootstrap Confidence Intervals with the Percentile Method
#>
#> Estimate 95% CI Lower 95% CI Upper p-value
#> ACME 0.3565 0.2119 0.51 <2e-16 ***
#> ADE 0.0396 -0.1750 0.28 0.760
#> Total Effect 0.3961 0.1743 0.64 0.004 **
#> Prop. Mediated 0.9000 0.5042 1.94 0.004 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Sample Size Used: 100
#>
#>
#> Simulations: 500
- Total Effect: \(\hat{c} = 0.3961\) → effect of \(X\) on \(Y\) without controlling for \(M\).
- Direct Effect (ADE): \(\hat{c'} = 0.0396\) → effect of \(X\) on \(Y\) after accounting for \(M\).
- ACME (Average Causal Mediation Effect):
ACME = \(\hat{c} - \hat{c'} = 0.3961 - 0.0396 = 0.3565\)
Equivalent to product of paths: \(\hat{a} \times \hat{b} = 0.56102 \times 0.6355 = 0.3565\).
These calculations do not rely on strong causal assumptions. For a causal interpretation, we need a more rigorous framework.
19.2.2 Two Approaches in Causal Mediation Analysis
The mediation
package Imai, Keele, and Yamamoto (2010) enables causal mediation analysis. It supports two inference types:
Model-Based Inference
Assumptions:
Treatment is randomized (or approximated via matching).
Sequential Ignorability: No unobserved confounding in:
Treatment → Mediator
Treatment → Outcome
Mediator → Outcome
This assumption is hard to justify in observational studies.
Design-Based Inference
- Relies on experimental design to isolate the causal mechanism.
Notation
We follow the standard potential outcomes framework:
\(M_i(t)\) = mediator under treatment condition \(t\)
\(T_i \in {0,1}\) = treatment assignment
\(Y_i(t, m)\) = outcome under treatment \(t\) and mediator value \(m\)
\(X_i\) = observed pre-treatment covariates
The treatment effect for an individual \(i\): \[ \tau_i = Y_i(1,M_i(1)) - Y_i (0,M_i(0)) \] which decomposes into:
- Causal Mediation Effect (ACME):
\[ \delta_i (t) = Y_i (t,M_i(1)) - Y_i(t,M_i(0)) \]
- Direct Effect (ADE):
\[ \zeta_i (t) = Y_i (1, M_i(1)) - Y_i(0, M_i(0)) \]
Summing up:
\[ \tau_i = \delta_i (t) + \zeta_i (1-t) \]
Sequential Ignorability Assumption
For CMA to be valid, we assume:
\[ \begin{aligned} \{ Y_i (t', m), M_i (t) \} &\perp T_i |X_i = x\\ Y_i(t',m) &\perp M_i(t) | T_i = t, X_i = x \end{aligned} \]
First condition is the standard strong ignorability condition where treatment assignment is random conditional on pre-treatment confounders.
Second condition is stronger where the mediators is also random given the observed treatment and pre-treatment confounders. This condition is satisfied only when there is no unobserved pre-treatment confounders, and post-treatment confounders, and multiple mediators that are correlated.
Key Challenge
⚠️ Sequential Ignorability is not testable. Researchers should conduct sensitivity analysis.
We now fit a causal mediation model using mediation
.
library(mediation)
set.seed(2014)
data("framing", package = "mediation")
# Step 1: Fit mediator model (M ~ T, X)
med.fit <-
lm(emo ~ treat + age + educ + gender + income, data = framing)
# Step 2: Fit outcome model (Y ~ M, T, X)
out.fit <-
glm(
cong_mesg ~ emo + treat + age + educ + gender + income,
data = framing,
family = binomial("probit")
)
# Step 3: Causal Mediation Analysis (Quasi-Bayesian)
med.out <-
mediate(
med.fit,
out.fit,
treat = "treat",
mediator = "emo",
robustSE = TRUE,
sims = 100
) # Use sims = 10000 in practice
summary(med.out)
#>
#> Causal Mediation Analysis
#>
#> Quasi-Bayesian Confidence Intervals
#>
#> Estimate 95% CI Lower 95% CI Upper p-value
#> ACME (control) 0.0791 0.0351 0.15 <2e-16 ***
#> ACME (treated) 0.0804 0.0367 0.16 <2e-16 ***
#> ADE (control) 0.0206 -0.0976 0.12 0.70
#> ADE (treated) 0.0218 -0.1053 0.12 0.70
#> Total Effect 0.1009 -0.0497 0.23 0.14
#> Prop. Mediated (control) 0.6946 -6.3109 3.68 0.14
#> Prop. Mediated (treated) 0.7118 -5.7936 3.50 0.14
#> ACME (average) 0.0798 0.0359 0.15 <2e-16 ***
#> ADE (average) 0.0212 -0.1014 0.12 0.70
#> Prop. Mediated (average) 0.7032 -6.0523 3.59 0.14
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Sample Size Used: 265
#>
#>
#> Simulations: 100
Alternative: Nonparametric Bootstrap
med.out <-
mediate(
med.fit,
out.fit,
boot = TRUE,
treat = "treat",
mediator = "emo",
sims = 100,
boot.ci.type = "bca"
)
summary(med.out)
#>
#> Causal Mediation Analysis
#>
#> Nonparametric Bootstrap Confidence Intervals with the BCa Method
#>
#> Estimate 95% CI Lower 95% CI Upper p-value
#> ACME (control) 0.0848 0.0424 0.14 <2e-16 ***
#> ACME (treated) 0.0858 0.0410 0.14 <2e-16 ***
#> ADE (control) 0.0117 -0.0726 0.13 0.58
#> ADE (treated) 0.0127 -0.0784 0.14 0.58
#> Total Effect 0.0975 0.0122 0.25 0.06 .
#> Prop. Mediated (control) 0.8698 1.7460 151.20 0.06 .
#> Prop. Mediated (treated) 0.8804 1.6879 138.91 0.06 .
#> ACME (average) 0.0853 0.0434 0.14 <2e-16 ***
#> ADE (average) 0.0122 -0.0756 0.14 0.58
#> Prop. Mediated (average) 0.8751 1.7170 145.05 0.06 .
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Sample Size Used: 265
#>
#>
#> Simulations: 100
If we suspect moderation, we include an interaction term.
med.fit <-
lm(emo ~ treat + age + educ + gender + income, data = framing)
out.fit <-
glm(
cong_mesg ~ emo * treat + age + educ + gender + income,
data = framing,
family = binomial("probit")
)
med.out <-
mediate(
med.fit,
out.fit,
treat = "treat",
mediator = "emo",
robustSE = TRUE,
sims = 100
)
summary(med.out)
#>
#> Causal Mediation Analysis
#>
#> Quasi-Bayesian Confidence Intervals
#>
#> Estimate 95% CI Lower 95% CI Upper p-value
#> ACME (control) 0.07417 0.02401 0.14 <2e-16 ***
#> ACME (treated) 0.09496 0.02702 0.16 <2e-16 ***
#> ADE (control) -0.01353 -0.11855 0.11 0.76
#> ADE (treated) 0.00726 -0.11007 0.11 0.90
#> Total Effect 0.08143 -0.05646 0.19 0.26
#> Prop. Mediated (control) 0.64510 -14.31243 3.13 0.26
#> Prop. Mediated (treated) 0.98006 -17.83202 4.01 0.26
#> ACME (average) 0.08457 0.02738 0.15 <2e-16 ***
#> ADE (average) -0.00314 -0.11457 0.12 1.00
#> Prop. Mediated (average) 0.81258 -16.07223 3.55 0.26
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Sample Size Used: 265
#>
#>
#> Simulations: 100
test.TMint(med.out, conf.level = .95) # Tests for interaction effect
#>
#> Test of ACME(1) - ACME(0) = 0
#>
#> data: estimates from med.out
#> ACME(1) - ACME(0) = 0.020796, p-value = 0.3
#> alternative hypothesis: true ACME(1) - ACME(0) is not equal to 0
#> 95 percent confidence interval:
#> -0.01757310 0.07110837
Since sequential ignorability is untestable, we examine how unmeasured confounding affects ACME estimates.
# Load required package
library(mediation)
# Simulate some example data
set.seed(123)
n <- 100
data <- data.frame(
treat = rbinom(n, 1, 0.5), # Binary treatment
med = rnorm(n), # Continuous mediator
outcome = rnorm(n) # Continuous outcome
)
# Fit the mediator model (med ~ treat)
med_model <- lm(med ~ treat, data = data)
# Fit the outcome model (outcome ~ treat + med)
outcome_model <- lm(outcome ~ treat + med, data = data)
# Perform mediation analysis
med_out <- mediate(med_model,
outcome_model,
treat = "treat",
mediator = "med",
sims = 100)
# Conduct sensitivity analysis
sens_out <- medsens(med_out, sims = 100)
# Print and plot results
summary(sens_out)
#>
#> Mediation Sensitivity Analysis for Average Causal Mediation Effect
#>
#> Sensitivity Region
#>
#> Rho ACME 95% CI Lower 95% CI Upper R^2_M*R^2_Y* R^2_M~R^2_Y~
#> [1,] -0.9 -0.6194 -1.3431 0.1043 0.81 0.7807
#> [2,] -0.8 -0.3898 -0.8479 0.0682 0.64 0.6168
#> [3,] -0.7 -0.2790 -0.6096 0.0516 0.49 0.4723
#> [4,] -0.6 -0.2067 -0.4552 0.0418 0.36 0.3470
#> [5,] -0.5 -0.1525 -0.3406 0.0355 0.25 0.2409
#> [6,] -0.4 -0.1083 -0.2487 0.0321 0.16 0.1542
#> [7,] -0.3 -0.0700 -0.1723 0.0323 0.09 0.0867
#> [8,] -0.2 -0.0354 -0.1097 0.0389 0.04 0.0386
#> [9,] -0.1 -0.0028 -0.0648 0.0591 0.01 0.0096
#> [10,] 0.0 0.0287 -0.0416 0.0990 0.00 0.0000
#> [11,] 0.1 0.0603 -0.0333 0.1538 0.01 0.0096
#> [12,] 0.2 0.0928 -0.0317 0.2173 0.04 0.0386
#> [13,] 0.3 0.1275 -0.0333 0.2882 0.09 0.0867
#> [14,] 0.4 0.1657 -0.0369 0.3684 0.16 0.1542
#> [15,] 0.5 0.2100 -0.0422 0.4621 0.25 0.2409
#> [16,] 0.6 0.2642 -0.0495 0.5779 0.36 0.3470
#> [17,] 0.7 0.3364 -0.0601 0.7329 0.49 0.4723
#> [18,] 0.8 0.4473 -0.0771 0.9717 0.64 0.6168
#> [19,] 0.9 0.6768 -0.1135 1.4672 0.81 0.7807
#>
#> Rho at which ACME = 0: -0.1
#> R^2_M*R^2_Y* at which ACME = 0: 0.01
#> R^2_M~R^2_Y~ at which ACME = 0: 0.0096
plot(sens_out)
- If ACME confidence intervals contain 0, the effect is not robust to confounding.
Alternatively, using \(R^2\) interpretation, we need to specify the direction of confounder that affects the mediator and outcome variables in plot
using sign.prod = "positive"
(i.e., same direction) or sign.prod = "negative"
(i.e., opposite direction).
Summary: Causal Mediation vs. Traditional Mediation
Aspect | Traditional Mediation | Causal Mediation |
---|---|---|
Model Assumption | Linear regressions | Potential outcomes framework |
Assumptions Needed | No omitted confounders | Sequential ignorability |
Inference Method | Product of coefficients | Counterfactual reasoning |
Bootstrapping? | Common | Essential |
Sensitivity Analysis? | Rarely used | Strongly recommended |