library(tidyverse)
library(psych)
library(MeMoBootR)mediation
Mediation
From statistics of doom YouTube.
Baron and Kenny (1986) method: 4 steps
- Path C total effect: the predictor predicts the outcome (X predicts Y). This step determines that there is a relation between X and Y that might be mediated by something else.
- Path A: the predictor predicts the mediator (X predicts M)
- Path B: mediator predicts outcomes, while including X; include both X + M in predicting Y.
- Path C`: The predictor must predict the outcome less strongly in model 3 than 1, if X no longer predicts Y, then the M completely mediates the relation between X and Y.
NOTE: no longer compulsory for X to significantly predict Y, more interested in change in prediction when we add M.
How much does the prediction have to change to say that there is mediation?
- traditionally all or nothing, c is significant, add m, c’ no longer significant, then fully mediated
- if c is still significant but prediction goes down -> partially mediated? question- how much does it need to go down?
Determine that via…
- The Sobel test
- OR Bootstrapping the indirect effect and confidence intervals (via memoBootR or psych package)
The manual way
X = predictor Y = outcome M = mediator
Run 3 models
## C Path X -> Y
model1 <- lm(outcome ~ predictor, data = data)
## A Path X -> M
model2 <- lm(mediator ~ predictor, data = data)
## B path X+M -> y
model3 <- lm(outcome ~ predictor + mediator, data = data)
Data example Tal-Or dataset
This example is described in the psych package vignette
Data comes from study Tal-Or et al
The Tal.Or data is embedded in the psych package. Read it as df.
df <- Tal.Ormediation question
Does presumed media influence (pmi) mediate the relation between front/back page (cond) and intention to act (reaction)?
predictor X = cond
outcome Y = reaction
mediator M = pmi
Manual method
Run the 3 models
Full mediation occurs if the X no longer predicts Y, when M is added. Partial mediation occurs when the degree to which X predicts Y is weakened, when M is added.
# manual method
## c Path X -> Y
model1 <- lm(reaction ~ cond, data = df)
## a Path X -> M
model2 <- lm(pmi ~ cond, data = df)
## b path X+M -> y
model3 <- lm(reaction ~ cond + pmi, data = df)Model summary
# X predicts Y, B = 0.50 (note p= 0.07)
summary(model1)
Call:
lm(formula = reaction ~ cond, data = df)
Residuals:
Min 1Q Median 3Q Max
-2.4957 -1.0000 -0.2457 1.2543 3.5000
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.2500 0.1906 17.052 <2e-16 ***
cond 0.4957 0.2775 1.786 0.0766 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.537 on 121 degrees of freedom
Multiple R-squared: 0.02568, Adjusted R-squared: 0.01763
F-statistic: 3.19 on 1 and 121 DF, p-value: 0.07661
# X predicts M, B = 0.48
summary(model2)
Call:
lm(formula = pmi ~ cond, data = df)
Residuals:
Min 1Q Median 3Q Max
-4.8534 -0.8534 0.1466 1.1231 1.6231
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.3769 0.1618 33.222 <2e-16 ***
cond 0.4765 0.2357 2.022 0.0454 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.305 on 121 degrees of freedom
Multiple R-squared: 0.03268, Adjusted R-squared: 0.02468
F-statistic: 4.088 on 1 and 121 DF, p-value: 0.0454
# M predicts Y, B = 0.51; and X predicts Y reduced to B = 0.25
summary(model3)
Call:
lm(formula = reaction ~ cond + pmi, data = df)
Residuals:
Min 1Q Median 3Q Max
-3.07636 -1.06128 -0.06346 0.94573 2.94299
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.52687 0.54968 0.958 0.340
cond 0.25435 0.25582 0.994 0.322
pmi 0.50645 0.09705 5.219 7.66e-07 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.393 on 120 degrees of freedom
Multiple R-squared: 0.2059, Adjusted R-squared: 0.1927
F-statistic: 15.56 on 2 and 120 DF, p-value: 9.83e-07
psych package
template code
```{r}
# psych method template code
model <- mediate(outcome ~ predictor + (mediator), data = data)
print(model)
```tal-or example
mod <- mediate(reaction ~ cond + (pmi), data = df)print()
# use print() to get short form results
print(mod)
Mediation/Moderation Analysis
Call: mediate(y = reaction ~ cond + (pmi), data = df)
The DV (Y) was reaction . The IV (X) was cond . The mediating variable(s) = pmi .
Total effect(c) of cond on reaction = 0.5 S.E. = 0.28 t = 1.79 df= 121 with p = 0.077
Direct effect (c') of cond on reaction removing pmi = 0.25 S.E. = 0.26 t = 0.99 df= 120 with p = 0.32
Indirect effect (ab) of cond on reaction through pmi = 0.24
Mean bootstrapped indirect effect = 0.24 with standard error = 0.13 Lower CI = 0.01 Upper CI = 0.52
R = 0.45 R2 = 0.21 F = 15.56 on 2 and 120 DF p-value: 1.31e-08
To see the longer output, specify short = FALSE in the print statement or ask for the summary
summary()
# use summary() to get long form results
summary(mod)Call: mediate(y = reaction ~ cond + (pmi), data = df)
Direct effect estimates (traditional regression) (c') X + M on Y
reaction se t df Prob
Intercept 0.53 0.55 0.96 120 3.40e-01
cond 0.25 0.26 0.99 120 3.22e-01
pmi 0.51 0.10 5.22 120 7.66e-07
R = 0.45 R2 = 0.21 F = 15.56 on 2 and 120 DF p-value: 9.83e-07
Total effect estimates (c) (X on Y)
reaction se t df Prob
Intercept 3.25 0.19 17.05 121 5.68e-34
cond 0.50 0.28 1.79 121 7.66e-02
'a' effect estimates (X on M)
pmi se t df Prob
Intercept 5.38 0.16 33.22 121 1.16e-62
cond 0.48 0.24 2.02 121 4.54e-02
'b' effect estimates (M on Y controlling for X)
reaction se t df Prob
pmi 0.51 0.1 5.22 120 7.66e-07
'ab' effect estimates (through all mediators)
reaction boot sd lower upper
cond 0.24 0.24 0.13 0.01 0.52
memoBootR package
Another option which does data checking for you as well comes from Stats of Doom Erin Buchanan- package called MeMoBootR
https://github.com/doomlab/MeMoBootR
template code
```{r}
saved = mediation1(y = "outcome",
x = "predictor",
m = "mediator",
cvs = NULL, # include covariates?
df = data,
with_out = T, # keep outliers
nboot = 1000,
conf_level = .95)
# c path
summary(saved$model1)
# a path
summary(saved$model2)
#B and c'path
summary(saved$model3)
```tal-or example
saved = mediation1(y = "reaction",
x = "cond",
m = "pmi",
cvs = NULL, #covariates
df = df,
with_out = T, # keep outliers
nboot = 1000,
conf_level = .95)Warning in boot.ci(bootresults, conf = conf_level, type = ci_type): bootstrap
variances needed for studentized intervals
summary()
# c path
summary(saved$model1)
Call:
lm(formula = allformulas$eq1, data = finaldata)
Residuals:
Min 1Q Median 3Q Max
-2.4957 -1.0000 -0.2457 1.2543 3.5000
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.2500 0.1906 17.052 <2e-16 ***
cond 0.4957 0.2775 1.786 0.0766 .
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.537 on 121 degrees of freedom
Multiple R-squared: 0.02568, Adjusted R-squared: 0.01763
F-statistic: 3.19 on 1 and 121 DF, p-value: 0.07661
# a path
summary(saved$model2)
Call:
lm(formula = allformulas$eq2, data = finaldata)
Residuals:
Min 1Q Median 3Q Max
-4.8534 -0.8534 0.1466 1.1231 1.6231
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 5.3769 0.1618 33.222 <2e-16 ***
cond 0.4765 0.2357 2.022 0.0454 *
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.305 on 121 degrees of freedom
Multiple R-squared: 0.03268, Adjusted R-squared: 0.02468
F-statistic: 4.088 on 1 and 121 DF, p-value: 0.0454
#B and c'path
summary(saved$model3)
Call:
lm(formula = allformulas$eq3, data = finaldata)
Residuals:
Min 1Q Median 3Q Max
-3.07636 -1.06128 -0.06346 0.94573 2.94299
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.52687 0.54968 0.958 0.340
cond 0.25435 0.25582 0.994 0.322
pmi 0.50645 0.09705 5.219 7.66e-07 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.393 on 120 degrees of freedom
Multiple R-squared: 0.2059, Adjusted R-squared: 0.1927
F-statistic: 15.56 on 2 and 120 DF, p-value: 9.83e-07