×

The following packages are used in this section: psych, tibble, and teachingtools. tibble are part of the tidyverse family.

To make sure that the packages used in this section are installed and loaded, run the following code in your console.

`xfun::pkg_attach2("psych","teachingtools","tidyverse")`

For mediation analysis I’m going to give a brief tour the psych package. The psych package isn’t your only option. In fact, you don’t need a special package for doing mediation analysis, and you could in fact do it just by fitting the appropriate regression models. The only tricky thing there would be calculating the bootstrapped confidence intervals, but these can be estimated with a package called mediation. However, this is overly complicated for the casual user of mediation analysis. The psych, in contrast does it all for you and you only have to specify your **X**, your **M**, and your **Y**.

Mediation in the psych is done with the `psych::mediate()`

function. In it’s simplest form it only requires the name of your **X**, **M**, and **Y** variables, and the name of your data table. To see it at work, we’ll replicate the first example from Hayes (2018)^{1}

In Chapter 3.3 Hayes (2018) introduces a data set from a study by Tal-Or, Cohen, Tsfati, and Gunther (2010).

(participants) read one of two newspaper articles describing an economic crisis that may affect the price and supply of sugar in Israel. Approximately half of the participants (n = 58) were given an article they were told would be appearing on the front page of a major Israeli newspaper (henceforth referred to as the front page condition). The remaining participants (n = 65) were given the same article but were told it would appear in the middle of an economic supplement of this newspaper (referred to here as the interior page condition).

After the participants read the article, they were asked a number of questions about their reactions to the story. Some questions asked par- ticipants how soon they planned on buying sugar and how much they intended to buy. Their responses were aggregated to form an intention to buy sugar measure (REACTION in the data file)

They were also asked questions used to quantify how much they believed that others in the community would be prompted to buy sugar as a result of exposure to the article, a measure of presumed media influence (PMI in the data file).

The aim was to:

estimate the effects of the manipulation (X […], with the front page condition coded 1 and the interior page condition coded 0) on likelihood of buying sugar (Y […]), directly as well as indirectly through presumed media influence (M […])

Let use try and replicate this analysis with `psych::mediate()`

.

First, we’ll take a look at our data table called `pmi`

:

`pmi`

```
# A tibble: 123 x 6
cond pmi import reaction gender age
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 7 6 5.25 1 51
2 0 6 1 1.25 1 40
3 1 5.5 6 5 1 26
4 0 6.5 6 2.75 0 21
5 0 6 5 2.5 1 27
6 0 5.5 1 1.25 1 25
7 0 3.5 1 1.5 0 23
8 1 6 6 4.75 1 25
9 0 4.5 6 4.25 1 22
10 0 7 6 6.25 1 24
# … with 113 more rows
```

The column labelled `cond`

will be our **X**, the column labelled `reaction`

will be our **Y**, and the column labelled `pmi`

will be our **M**. We’ll save the model to `hayes1`

,

```
hayes1 <- psych::mediate(x = "cond", # our X
y = "reaction", # our Y
m = "pmi", # our M
data = pmi, # our data table
n.iter = 5000, # the number of bootstrap samples (default: 5000)
plot = FALSE, # don't draw a plot (default: TRUE)
)
```

To view the model output we can just type in the model name `hayes1`

to access this.

`hayes1`

```
Mediation/Moderation Analysis
Call: psych::mediate(y = "reaction", x = "cond", m = "pmi", data = pmi,
n.iter = 5000, plot = FALSE)
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= 122 with p = 0.075
Direct effect (c') of cond on reaction removing pmi = 0.25 S.E. = 0.55 t = 0.96 df= 120 with p = 0.34
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 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
```

The model output will give us the statistics for the **Total effect**, the **Direct effect**, and the **Indirect effect**, including the bootstrapped confidence intervals for the **Indirect effect**.

Another way to access the information about the model is to use the **generic** function `summary()`

`summary(hayes1)`

```
Call: psych::mediate(y = "reaction", x = "cond", m = "pmi", data = pmi,
n.iter = 5000, plot = FALSE)
Direct effect estimates (traditional regression) (c')
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)
reaction se t df Prob
cond 0.5 0.28 1.79 122 0.0754
'a' effect estimates
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
reaction se t df Prob
pmi 0.51 0.1 5.24 121 6.88e-07
'ab' effect estimates (through mediators)
reaction boot sd lower upper
cond 0.24 0.24 0.13 0 0.52
```

If we do want to view the model diagram we can use the `mediate.diagram()`

function. Compare the plot below to the one in Hayes (2018, pg 88) if you’d like.

`psych::mediate.diagram(hayes1)`

One big downside of the psych package is that the model object is difficult to work with. For example, let’s say that we just wanted to get the bootstrapped confidence intervals for the indirect effect, and we wanted to save that to a variable. There is unfortunately no straightforward way to do this. However, all the information is saved in a list inside the output object and you could access it by subsetting.

For example:

The mean of **ab**

`hayes1[["boot"]][['mean']][,1]`

```
cond
0.2433902
```

The sd of **ab**

`hayes1[["boot"]][['sd']][,1]`

```
cond
0.1305335
```

The bootstrapped CIs of **ab**

`hayes1[["boot"]][['ci']][,1]`

```
2.5% 97.5%
0.003656523 0.523096406
```

Another big downside of the psych package is that it isn’t that great beyond simple examples like the one I’ve demonstrated. However, if you’re just interested in doing simple mediation, then the psych package might be a more user friendly alternative to the SPSS `PROCESS`

macro.

For more complex scenarios the go to package is lavaan. lavaan is a package for doing SEM but obviously it can also do simple mediation analysis. However, covering lavaan would take a workshop in itself because the syntax and approach is a lot more complex. Below, just for an illustration, I’ve included an example of how to replicate with lavaan what we did in psych.

```
xfun::pkg_attach2("lavaan")
model <- ' # direct effect
reaction ~ c*cond
# mediator
pmi ~ a*cond
reaction ~ b*pmi
# indirect effect (a*b)
ab := a*b
# total effect
total := c + (a*b)
'
fit <- lavaan::sem(model = model, data = pmi, se = "bootstrap")
summary(fit)
```

```
lavaan 0.6-6 ended normally after 21 iterations
Estimator ML
Optimization method NLMINB
Number of free parameters 5
Number of observations 123
Model Test User Model:
Test statistic 0.000
Degrees of freedom 0
Parameter Estimates:
Standard errors Bootstrap
Number of requested bootstrap draws 1000
Number of successful bootstrap draws 986
Regressions:
Estimate Std.Err z-value P(>|z|)
reaction ~
cond (c) 0.254 0.266 0.957 0.339
pmi ~
cond (a) 0.477 0.232 2.052 0.040
reaction ~
pmi (b) 0.506 0.083 6.104 0.000
Variances:
Estimate Std.Err z-value P(>|z|)
.reaction 1.893 0.201 9.441 0.000
.pmi 1.675 0.289 5.788 0.000
Defined Parameters:
Estimate Std.Err z-value P(>|z|)
ab 0.241 0.129 1.876 0.061
total 0.496 0.288 1.718 0.086
```

Hayes, A. F. (2018) Introduction to Mediation, Moderation, and Conditional Process Analysis (2nd Edition), Guilford Press, London.↩︎