Skip to content

Commit 2972766

Browse files
Benjamin T. VincentdrbenvincentOriolAbril
authored
Update Mediation analysis notebook to best practice (#280)
* create truncated regression example * delete truncated regression example from main branch * create truncated regression example * delete truncated regression example from main branch * create truncated regression example * delete truncated regression example from main branch * update to best practice * get watermark header right * remove silly "," from tags * fix references, hopefully * fix in text citations * add 'path analysis' as a tag * fix error in description of total effect * combine some cells, for simplicity * update estimate which is off by 1dp under v4 for some reason * add dims="obs_id" to ConstantData * remove reference to "now" in terms of current best practice * improve DAG and fix typo * add in a dims="obs_id" * run pre commit hook Co-authored-by: Benjamin T. Vincent <[email protected]> Co-authored-by: Oriol (ZBook) <[email protected]>
1 parent c142ef4 commit 2972766

File tree

3 files changed

+385
-353
lines changed

3 files changed

+385
-353
lines changed

examples/case_studies/mediation_analysis.ipynb

Lines changed: 305 additions & 306 deletions
Large diffs are not rendered by default.

examples/references.bib

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ @misc{harper2015movielens
103103
month = {January},
104104
url = {https://doi.org/10.1145/2827872}
105105
}
106+
@book{hayes2017introduction,
107+
title = {Introduction to mediation, moderation, and conditional process analysis: A regression-based approach},
108+
author = {Hayes, Andrew F},
109+
year = {2017},
110+
publisher = {Guilford publications}
111+
}
106112
@misc{hogg2010data,
107113
title = {Data analysis recipes: Fitting a model to data},
108114
author = {David W. Hogg and Jo Bovy and Dustin Lang},
@@ -159,6 +165,16 @@ @article{koren2009matrixfactorization
159165
pages = {30--37},
160166
doi = {10.1109/MC.2009.263}
161167
}
168+
@article{kruschke2011bayesian,
169+
title = {Bayesian assessment of null values via parameter estimation and model comparison},
170+
author = {Kruschke, John K},
171+
journal = {Perspectives on Psychological Science},
172+
volume = {6},
173+
number = {3},
174+
pages = {299--312},
175+
year = {2011},
176+
publisher = {Sage Publications Sage CA: Los Angeles, CA}
177+
}
162178
@article{kruschke2013,
163179
doi = {10.1037/a0029146},
164180
url = {https://doi.org/10.1037/a0029146},
@@ -244,6 +260,16 @@ @article{nowlan1992simplifying
244260
year = {1992},
245261
publisher = {MIT Press}
246262
}
263+
@article{nuijten2015default,
264+
title = {A default Bayesian hypothesis test for mediation},
265+
author = {Nuijten, Mich{\`e}le B and Wetzels, Ruud and Matzke, Dora and Dolan, Conor V and Wagenmakers, Eric-Jan},
266+
journal = {Behavior research methods},
267+
volume = {47},
268+
number = {1},
269+
pages = {85--97},
270+
year = {2015},
271+
publisher = {Springer}
272+
}
247273
@book{roback2021beyond,
248274
title = {Beyond multiple linear regression: Applied generalized linear models and multilevel models in R},
249275
author = {Roback, P., and Legler, J.},
@@ -294,3 +320,13 @@ @book{wilkinson2005grammar
294320
issn = {1431-8784},
295321
isbn = {978-0-387-24544-7}
296322
}
323+
@article{yuan2009bayesian,
324+
title = {Bayesian mediation analysis.},
325+
author = {Yuan, Ying and MacKinnon, David P},
326+
journal = {Psychological methods},
327+
volume = {14},
328+
number = {4},
329+
pages = {301},
330+
year = {2009},
331+
publisher = {American Psychological Association}
332+
}

myst_nbs/case_studies/mediation_analysis.myst.md

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,29 @@ jupytext:
66
format_version: 0.13
77
jupytext_version: 1.13.7
88
kernelspec:
9-
display_name: Python 3
9+
display_name: Python 3 (ipykernel)
1010
language: python
1111
name: python3
1212
---
1313

14+
(mediation_analysis)=
1415
# Bayesian mediation analysis
1516

16-
**Author:** [Benjamin T. Vincent](https://github.com/drbenvincent)
17+
:::{post} February, 2022
18+
:tags: mediation, path analysis, pymc3.ConstantData, pymc3.Deterministic, pymc3.HalfCauchy, pymc3.Model, pymc3.Normal, regression
19+
:category: beginner
20+
:author: Benjamin T. Vincent
21+
:::
1722

1823
This notebook covers Bayesian [mediation analysis](https://en.wikipedia.org/wiki/Mediation_(statistics) ). This is useful when we want to explore possible mediating pathways between a predictor and an outcome variable.
1924

20-
It is important to note that the approach to mediation analysis has evolved over time. This notebook will attempt to use best practice as of now, and is heavily influenced by the approach of Hayes (2018) as set out in his textbook "Introduction to Mediation, Moderation and Conditional Process Analysis."
25+
It is important to note that the approach to mediation analysis has evolved over time. This notebook was heavily influenced by the approach of {cite:t}`hayes2017introduction` as set out in his textbook "Introduction to Mediation, Moderation and Conditional Process Analysis."
2126

2227
```{code-cell} ipython3
2328
import arviz as az
2429
import matplotlib.pyplot as plt
2530
import numpy as np
26-
import pymc3 as pm
31+
import pymc as pm
2732
import seaborn as sns
2833
2934
from pandas import DataFrame
@@ -52,10 +57,10 @@ where $i$ indexes each observation (row in the dataset), and $i_M$ and $i_Y$ are
5257

5358
![](mediation.png)
5459

55-
Using definitions from Hayes (2018), we can define a few effects of interest:
60+
Using definitions from {cite:t}`hayes2017introduction`, we can define a few effects of interest:
5661
- **Direct effect:** is given by $c'$. Two cases that differ by one unit on $x$ but are equal on $m$ are estimated to differ by $c'$ units on $y$.
5762
- **Indirect effect:** is given by $a \cdot b$. Two cases which differ by one unit of $x$ are estimated to differ by $a \cdot b$ units on $y$ as a result of the effect of $x \rightarrow m$ and $m \rightarrow y$.
58-
- **Total effect:** is $c = c' + a \cdot b$ which is simply the sum of the direct and indirect effects. This could be understood as: two cases that differ by one unit on $x$ are estimated to differ by $a \cdot b$ units on $y$ due to both the direct pathway $x \rightarrow y$ and the indirect pathway $c \rightarrow m \rightarrow m$. The total effect could also be estimated by evaluating the alternative model $y_i \sim \mathrm{Normal}(i_{Y*} + c \cdot x_i, \sigma_{Y*})$.
63+
- **Total effect:** is $c = c' + a \cdot b$ which is simply the sum of the direct and indirect effects. This could be understood as: two cases that differ by one unit on $x$ are estimated to differ by $a \cdot b$ units on $y$ due to the indirect pathway $x \rightarrow m \rightarrow y$, and by $c'$ units due to the direct pathway $x \rightarrow y$. The total effect could also be estimated by evaluating the alternative model $y_i \sim \mathrm{Normal}(i_{Y*} + c \cdot x_i, \sigma_{Y*})$.
5964

6065
+++
6166

@@ -85,9 +90,9 @@ sns.pairplot(DataFrame({"x": x, "m": m, "y": y}));
8590
```{code-cell} ipython3
8691
def mediation_model(x, m, y):
8792
with pm.Model() as model:
88-
x = pm.Data("x", x)
89-
y = pm.Data("y", y)
90-
m = pm.Data("m", m)
93+
x = pm.ConstantData("x", x, dims="obs_id")
94+
y = pm.ConstantData("y", y, dims="obs_id")
95+
m = pm.ConstantData("m", m, dims="obs_id")
9196
9297
# intercept priors
9398
im = pm.Normal("im", mu=0, sigma=10)
@@ -101,41 +106,30 @@ def mediation_model(x, m, y):
101106
σy = pm.HalfCauchy("σy", 1)
102107
103108
# likelihood
104-
pm.Normal("m_likehood", mu=im + a * x, sigma=σm, observed=m)
105-
pm.Normal("y_likehood", mu=iy + b * m + cprime * x, sigma=σy, observed=y)
109+
pm.Normal("m_likelihood", mu=im + a * x, sigma=σm, observed=m, dims="obs_id")
110+
pm.Normal("y_likelihood", mu=iy + b * m + cprime * x, sigma=σy, observed=y, dims="obs_id")
106111
107112
# calculate quantities of interest
108113
indirect_effect = pm.Deterministic("indirect effect", a * b)
109114
total_effect = pm.Deterministic("total effect", a * b + cprime)
110115
111116
return model
112-
```
113117
114-
```{code-cell} ipython3
115-
model = mediation_model(x, m, y)
116-
```
117118
118-
```{code-cell} ipython3
119+
model = mediation_model(x, m, y)
119120
pm.model_to_graphviz(model)
120121
```
121122

122123
```{code-cell} ipython3
123124
with model:
124-
result = pm.sample(
125-
2000,
126-
tune=4000,
127-
chains=2,
128-
target_accept=0.9,
129-
random_seed=42,
130-
return_inferencedata=True,
131-
idata_kwargs={"dims": {"x": ["obs_id"], "m": ["obs_id"], "y": ["obs_id"]}},
132-
)
125+
result = pm.sample(tune=4000, target_accept=0.9, random_seed=42)
133126
```
134127

135128
Visualise the trace to check for convergence.
136129

137130
```{code-cell} ipython3
138-
az.plot_trace(result);
131+
az.plot_trace(result)
132+
plt.tight_layout()
139133
```
140134

141135
We have good chain mixing and the posteriors for each chain look very similar, so no problems in that regard.
@@ -171,7 +165,7 @@ ax = az.plot_posterior(
171165
ax[0].set(title="direct effect");
172166
```
173167

174-
- The posterior mean **direct effect** is 0.28, meaning that for every 1 unit of increase in $x$, $y$ increases by 0.28 due to the direct effect $x \rightarrow y$.
168+
- The posterior mean **direct effect** is 0.29, meaning that for every 1 unit of increase in $x$, $y$ increases by 0.29 due to the direct effect $x \rightarrow y$.
175169
- The posterior mean **indirect effect** is 0.49, meaning that for every 1 unit of increase in $x$, $y$ increases by 0.49 through the pathway $x \rightarrow m \rightarrow y$. The probability that the indirect effect is zero is infintesimal.
176170
- The posterior mean **total effect** is 0.77, meaning that for every 1 unit of increase in $x$, $y$ increases by 0.77 through both the direct and indirect pathways.
177171

@@ -182,25 +176,17 @@ Above, we stated that the total effect could also be estimated by evaluating the
182176

183177
```{code-cell} ipython3
184178
with pm.Model() as total_effect_model:
185-
_x = pm.Data("_x", x)
179+
_x = pm.ConstantData("_x", x, dims="obs_id")
186180
iy = pm.Normal("iy", mu=0, sigma=1)
187181
c = pm.Normal("c", mu=0, sigma=1)
188182
σy = pm.HalfCauchy("σy", 1)
189183
μy = iy + c * _x
190-
_y = pm.Normal("_y", mu=μy, sd=σy, observed=y)
184+
pm.Normal("yy", mu=μy, sd=σy, observed=y, dims="obs_id")
191185
```
192186

193187
```{code-cell} ipython3
194188
with total_effect_model:
195-
total_effect_result = pm.sample(
196-
2000,
197-
tune=4000,
198-
chains=2,
199-
target_accept=0.9,
200-
random_seed=42,
201-
return_inferencedata=True,
202-
idata_kwargs={"dims": {"x": ["obs_id"], "y": ["obs_id"]}},
203-
)
189+
total_effect_result = pm.sample(tune=4000, target_accept=0.9, random_seed=42)
204190
```
205191

206192
```{code-cell} ipython3
@@ -218,25 +204,36 @@ As we can see, the posterior distributions over the direct effects are near-iden
218204
+++
219205

220206
## Parameter estimation versus hypothesis testing
221-
This notebook has focussed on the approach of Bayesian parameter estimation. For many situations this is entirely sufficient, and more information can be found in Yuan & MacKinnon (2009). It will tell us, amongst other things, what our posterior beliefs are in the direct effects, indirect effects, and total effects. And we can use those posterior beliefs to conduct posterior predictive checks to visually check how well the model accounts for the data.
207+
This notebook has focussed on the approach of Bayesian parameter estimation. For many situations this is entirely sufficient, and more information can be found in {cite:t}`yuan2009bayesian`. It will tell us, amongst other things, what our posterior beliefs are in the direct effects, indirect effects, and total effects. And we can use those posterior beliefs to conduct posterior predictive checks to visually check how well the model accounts for the data.
222208

223-
However, depending upon the use case it may be preferable to test hypotheses about the presence or absence of an indirect effect ($x \rightarrow m \rightarrow y$) for example. In this case, it may be more appropriate to take a more explicit hypothesis testing approach to see examine the relative credibility of the mediation model as compared to a simple direct effect model (i.e. $y_i = \mathrm{Normal}(i_{Y*} + c \cdot x_i, \sigma_{Y*})$). Readers are referred to Nuijten et al (2014) for a hypothesis testing approach to Bayesian mediation models and to Kruschke (2011) for more information on parameter estimation versus hypothesis testing.
209+
However, depending upon the use case it may be preferable to test hypotheses about the presence or absence of an indirect effect ($x \rightarrow m \rightarrow y$) for example. In this case, it may be more appropriate to take a more explicit hypothesis testing approach to see examine the relative credibility of the mediation model as compared to a simple direct effect model (i.e. $y_i = \mathrm{Normal}(i_{Y*} + c \cdot x_i, \sigma_{Y*})$). Readers are referred to {cite:t}`nuijten2015default` for a hypothesis testing approach to Bayesian mediation models and to {cite:t}`kruschke2011bayesian` for more information on parameter estimation versus hypothesis testing.
224210

225211
+++
226212

227213
## Summary
228-
As stated at the outset, the procedures used in mediation analysis have evolved over time. So there are plenty of people who are not necessarily up to speed with modern best practice. The approach in this notebook sticks to that outlined by Hayes (2018), but it is relevant to be aware of some of this history to avoid confusion - which is particularly important if defending your approach in peer review.
214+
As stated at the outset, the procedures used in mediation analysis have evolved over time. So there are plenty of people who are not necessarily up to speed with modern best practice. The approach in this notebook sticks to that outlined by {cite:t}`hayes2017introduction`, but it is relevant to be aware of some of this history to avoid confusion - which is particularly important if defending your approach in peer review.
229215

230216
+++
231217

232-
# References
218+
## Authors
219+
- Authored by Benjamin T. Vincent in August 2021
220+
- Updated by Benjamin T. Vincent in February 2022
233221

234-
- Hayes, A. F. (2018). Introduction to Mediation, Moderation, and Conditional Process Analysis: A Regression‐Based Approach. New York: Guilford Press. Retrieved from https://doi.org/10.1111/jedm.12050
235-
- Kruschke, J. (2011). Bayesian Assessment of Null Values Via Parameter Estimation and Model Comparison. Perspectives on Psychological Science, 6(3), 299–312. Retrieved from https://doi.org/10.1177/1745691611406925
236-
- Nuijten, M. B., Wetzels, R., Matzke, D., Dolan, C. V., & Wagenmakers, E.-J. (2014). A default Bayesian hypothesis test for mediation. Behavior Research Methods, 47(1), 85–97. http://doi.org/10.3758/s13428-014-0470-2
237-
- Yuan, Y., & MacKinnon, D. P. (2009). Bayesian mediation analysis. Psychological Methods, 14(4), 301–322. http://doi.org/10.1037/a0016972
222+
+++
223+
224+
## References
225+
:::{bibliography}
226+
:filter: docname in docnames
227+
:::
228+
229+
+++
230+
231+
## Watermark
238232

239233
```{code-cell} ipython3
240234
%load_ext watermark
241-
%watermark -n -u -v -iv -w -p theano,xarray
235+
%watermark -n -u -v -iv -w -p aesara,aeppl,xarray
242236
```
237+
238+
:::{include} ../page_footer.md
239+
:::

0 commit comments

Comments
 (0)