PyProcessMacro 1.0.12__tar.gz → 1.0.14__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/LICENSE.txt +0 -0
  2. pyprocessmacro-1.0.14/MANIFEST.in +4 -0
  3. pyprocessmacro-1.0.14/PKG-INFO +611 -0
  4. pyprocessmacro-1.0.14/PyProcessMacro.egg-info/PKG-INFO +611 -0
  5. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/PyProcessMacro.egg-info/SOURCES.txt +4 -3
  6. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/PyProcessMacro.egg-info/dependency_links.txt +0 -0
  7. pyprocessmacro-1.0.14/PyProcessMacro.egg-info/requires.txt +8 -0
  8. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/PyProcessMacro.egg-info/top_level.txt +0 -1
  9. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/README.md +23 -17
  10. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/pyprocessmacro/__init__.py +1 -1
  11. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/pyprocessmacro/models.py +25 -12
  12. pyprocessmacro-1.0.14/pyprocessmacro/models.pyi +228 -0
  13. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/pyprocessmacro/process.py +45 -29
  14. pyprocessmacro-1.0.14/pyprocessmacro/process.pyi +163 -0
  15. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/pyprocessmacro/utils.py +8 -6
  16. pyprocessmacro-1.0.14/pyprocessmacro/utils.pyi +92 -0
  17. pyprocessmacro-1.0.14/pyproject.toml +67 -0
  18. {PyProcessMacro-1.0.12 → pyprocessmacro-1.0.14}/setup.cfg +0 -0
  19. PyProcessMacro-1.0.12/MANIFEST.in +0 -2
  20. PyProcessMacro-1.0.12/PKG-INFO +0 -591
  21. PyProcessMacro-1.0.12/PyProcessMacro.egg-info/PKG-INFO +0 -591
  22. PyProcessMacro-1.0.12/PyProcessMacro.egg-info/requires.txt +0 -5
  23. PyProcessMacro-1.0.12/setup.py +0 -41
  24. PyProcessMacro-1.0.12/tests/__init__.py +0 -0
  25. PyProcessMacro-1.0.12/tests/test_models_accuracy.py +0 -147
@@ -0,0 +1,4 @@
1
+ # Keep the sdist library-only. The accuracy tests depend on 14 MB of PROCESS
2
+ # fixture files that are not distributed, so shipping the test module alone
3
+ # would be misleading. Tests run from a git checkout (see .github/workflows).
4
+ prune tests
@@ -0,0 +1,611 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyProcessMacro
3
+ Version: 1.0.14
4
+ Summary: A Python library for moderation, mediation and conditional process analysis. Based on Andrew F. Hayes' Process Macro.
5
+ Author-email: Quentin André <quentin.andre@insead.edu>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/QuentinAndre/pyprocessmacro
8
+ Project-URL: Repository, https://github.com/QuentinAndre/pyprocessmacro
9
+ Project-URL: Issues, https://github.com/QuentinAndre/pyprocessmacro/issues
10
+ Project-URL: Changelog, https://github.com/QuentinAndre/pyprocessmacro/blob/master/CHANGELOG.md
11
+ Keywords: mediation-analysis,statistics,process,plotting,data-science,data-analysis,data-visualization,regression-models
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Natural Language :: English
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Requires-Python: >=3.11
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE.txt
25
+ Requires-Dist: numpy>=1.26
26
+ Requires-Dist: pandas>=2.0
27
+ Requires-Dist: scipy>=1.10
28
+ Requires-Dist: matplotlib>=3.7
29
+ Requires-Dist: seaborn>=0.13
30
+ Provides-Extra: test
31
+ Requires-Dist: pytest>=8; extra == "test"
32
+ Dynamic: license-file
33
+
34
+ PyProcessMacro: A Python Implementation of Andrew F. Hayes' 'Process' Macro
35
+ ============================================================================
36
+
37
+ [![CI](https://github.com/QuentinAndre/pyprocessmacro/actions/workflows/ci.yml/badge.svg)](https://github.com/QuentinAndre/pyprocessmacro/actions/workflows/ci.yml)
38
+
39
+ # Copyright Notice for the original Process Macro
40
+
41
+ The Process Macro for SAS and SPSS, and its associated files, are copyrighted by Andrew F. Hayes. The original code
42
+ must not be edited or modified, and must not be distributed outside of
43
+ [http://www.processmacro.org](http://www.processmacro.org).
44
+
45
+ Because PyProcessMacro is a complete reimplementation of the Process Macro, and was not based on the original
46
+ code, permission was generously granted by Andrew F. Hayes to distribute PyProcessMacro under a MIT license.
47
+
48
+ This permission is not an endorsement of PyProcessMacro: all potential errors, bugs and inaccuracies are my own, and
49
+ Andrew F. Hayes was not involved in writing, reviewing, or debugging the code.
50
+
51
+ # Manifest
52
+
53
+ The Process Macro by Andrew F. Hayes has helped thousands of researchers in their analysis of moderation, mediation, and
54
+ conditional processes. Unfortunately, Process was only available for proprietary softwares (SAS and SPSS), which means
55
+ that students and researchers had to purchase a license of those softwares to make use of the Macro.
56
+
57
+ Because of the growing popularity of Python in the scientific community, I decided to implement the features of the
58
+ Process Macro into an open-source library, that researchers will be able to use without relying on those proprietary
59
+ softwaress. PyProcessMacro is released under a MIT license.
60
+
61
+ # Features
62
+
63
+ In the current version, PyProcessMacro replicates the following features from the original Process Macro v2.16:
64
+ * All models (1 to 76), with the exception of Model 6 (serial mediation) are supported, and have been numerically
65
+ tested for accuracy against the output of the original Process macro (see the `test_models_accuracy.py`)
66
+ * Estimation of binary/continuous outcome variables. The binary outcomes are estimated in Logit using the
67
+ Newton-Raphson convergence algorithm, the continuous variables are estimated using OLS.
68
+ * All statistics reported by Process:
69
+ * Variable parameters for outcome models
70
+ * (Conditional) direct and indirect effects
71
+ * Indices for Partial/Conditional/Moderated Moderated Mediation are always reported if the model supports them.
72
+ * Automatic generation of spotlight values for continuous/discrete moderators.
73
+ * Rich set of options to tweak the estimation and display of the different models: (almost) all the options from
74
+ Process exist in PyProcessMacro. Check the doc for more details.
75
+
76
+ The following changes and improvements have been made from the original Process Macro:
77
+ * Variable names can be of any length, and even include spaces and special characters.
78
+ * All mediation models support an infinite number of mediators (versus a maximum of 10 in Process).
79
+ * Normal theory tests for the indirect effect(s) are not reported, as the bootstrapping approach is now widely
80
+ accepted and in most cases more robust.
81
+ * Plotting capabilities: PyProcessMacro can generate the plot of conditional direct and indirect effects at various
82
+ levels of the moderators. See the documentation for plot_conditional_indirect_effects() and
83
+ plot_conditional_direct_effects().
84
+ * Fast estimation process: PyProcessMacro leverages the capabilities of NumPy to efficiently compute a large number
85
+ of bootstrap estimates, and dramatically speed up the estimation of complex models.
86
+ * Transparent bootstrapping: PyProcessMacro explicitely reports the number of bootstrap samples that have been
87
+ discarded because of numerical instability.
88
+
89
+ In the current version, the following features have not yet been ported to PyProcessMacro:
90
+ * Support for categorical independent variables.
91
+ * Generation of individual fixed effects for repeated measures.
92
+ * R² improvement from moderators in moderation models (1, 2, 3).
93
+ * Estimation of serial mediation (Model 6)
94
+ * Some options (`normal`, `varorder`, ...). PyProcessMacro will issue a warning to tell you if an option you are
95
+ trying to use is not implemented.
96
+
97
+ # Version History
98
+
99
+ ## Master Versions
100
+
101
+ ### 1.0.12 and later
102
+
103
+ See [CHANGELOG.md](CHANGELOG.md).
104
+
105
+ ### 1.0.11
106
+ **Various doc and bug fixes**
107
+ In particular, the Moderated Mediation index (MM_index_summary()) was not displayed.
108
+
109
+ ### 1.0.8
110
+ **Bug fix on plot_conditional_(in)direct effects**
111
+ An error warning was unnecessarily generated for some variable names. This has now been fixed.
112
+
113
+ ### 1.0.5
114
+ **Bug fix on newer numpy version**
115
+ A recent numpy version was causing PyProcessMacro to crash on non-float data. Thanks to William Harding for the bug
116
+ report and for the fix.
117
+
118
+ ### 1.0.4
119
+ **Bug fix for standard error estimate in all models**
120
+ PyProcessMacro was, by default, using the HC3 estimator for the variance-covariance matrix instead of the HC0 estimator.
121
+ This has now been changed. To continue using the HC3 estimator, specify `hc3=True` when initializing the Process instance.
122
+ Thanks to Zoé Ziani for the bug report.
123
+
124
+ ### 1.0.3
125
+ **Bug fix for Models 58 and 59**
126
+ The number of moderators was not properly computed, and pyprocessmacro was crashing on those two models. It has now
127
+ been fixed. Thanks to amrain-py for the bug report.
128
+
129
+ ### 1.0.2
130
+ **Bug fix in the Index of Moderated Moderated Mediation**
131
+ In the summary, the Index of Moderated Moderated Mediation was reported as a zero-width confidence interval.
132
+
133
+ ### 1.0.0
134
+ **Added support for floodlight analysis (Johnson-Neyman region of significance).**
135
+
136
+ The methods `floodlight_direct_effect()` and `floodlight_indirect_effect()` can now be used to find the range of values
137
+ at which an effect is significant. See the documentation for more information on those methods.
138
+
139
+ **Added methods: `spotlight_direct_effect()` and `spotlight_indirect_effect()`.**
140
+
141
+ Those methods can be used to compute the conditional (in)direct effects of the models at various levels of the
142
+ moderators.
143
+
144
+ **Deprecation of `plot_direct_effects()` and `plot_indirect_effects()`.**
145
+
146
+ Those methods have been deprecated in favor of `plot_conditional_direct_effects()` and
147
+ `plot_conditional_indirect_effects()` respectively.
148
+
149
+ The signature of the function has also changed: the argument `mods_at` has been renamed `modval` for consistency with
150
+ other functions. Under the hood, those functions are faster and are using the newly introduced
151
+ `spotlight_direct_effect()` and `spotlight_indirect_effect()` methods.
152
+
153
+ ## Beta versions
154
+
155
+ ### 0.9.6 -> 0.9.7
156
+
157
+ * Added support for Moderation Mediation Index in single moderator models.
158
+ * Performance improvements
159
+ * Dependency updates
160
+ * Added tests
161
+
162
+ ### 0.9.1 -> 0.9.5
163
+ * Various bugfixes
164
+ * Performance improvements
165
+
166
+ ### 0.9.0
167
+ First beta release.
168
+
169
+ # Installation and Documentation
170
+
171
+ This section will familiarize you with the few differences that exist between Process and PyProcessMacro.
172
+
173
+ PyProcessMacro requires Python 3.11 or newer. You can install it with pip:
174
+
175
+ pip install pyprocessmacro
176
+
177
+ ## 1. Initializing a Process object
178
+
179
+ ### A. Minimal example
180
+
181
+ The basic syntax for PyProcessMacro is the following:
182
+
183
+ ````python
184
+ from pyprocessmacro import Process
185
+ import pandas as pd
186
+ df = pd.read_csv("MyDataset.csv")
187
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
188
+ m=["MediationSkills", "ModerationSkills"])
189
+ p.summary()
190
+ ````
191
+
192
+ [Click to see a sample output!](SampleOutput.md)
193
+
194
+ As you can see, the syntax for PyProcessMacro is (almost) identical to that of Process. Unless this documentation
195
+ mentions otherwise, you can assume that all the options/keywords from Process exist in PyProcessMacro.
196
+
197
+ A `Process` object is initialized by specifying a data source, the model number, and the mapping between the symbols
198
+ and the variable names.
199
+
200
+ Once the object is initialized, you can call its `summary()` method to display the estimation results
201
+
202
+ You might have noticed that there is no argument `varlist` in PyProcessMacro. This is because the list of variables
203
+ is automatically inferred from the variable names given to x, y, m.
204
+
205
+ ### B. Adding statistical controls
206
+
207
+ In Process, the controls are defined as "any argument in the varlist that is not the IV, the DV, a moderator, or
208
+ a mediator." In PyProcessMacro, the list of variables to include as controls have to be explicitely specified in
209
+ the "controls" argument.
210
+
211
+ The equation(s) to which the controls are added is specified through the `controls_in` argument:
212
+ * `x_to_m` means that the controls will be added in the path from the IV to the mediator(s) only.
213
+ * `all_to_y` means that the controls will be added in the path from the IV and the mediators to the DV only.
214
+ * `all` means that the controls will be added in all equations.
215
+
216
+ The ability to specify a different list of control for each equation is coming in the next release of PyProcessMacro.
217
+
218
+ ````python
219
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
220
+ m=["MediationSkills", "ModerationSkills"],
221
+ controls=["Control1", "Control2"],
222
+ controls_in="all")
223
+ p.summary()
224
+ ````
225
+
226
+ ### C. Logistic regression for binary outcomes
227
+
228
+ The original Process Macro automatically uses a Logistic (instead of OLS) regression when it detects a binary outcome.
229
+
230
+ PyProcessMacro prefers a more explicit approach, and requires you to set the parameter `logit` to `True` if your DV
231
+ should be estimated using a Logistic regression.
232
+
233
+ ````python
234
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
235
+ m=["MediationSkills", "ModerationSkills"], logit=True)
236
+ p.summary()
237
+ ````
238
+
239
+ It goes without saying that this will return an error if your DV is not dichotomous.
240
+
241
+ ### D. Specifying custom spotlight values for the moderator(s)
242
+
243
+ In Process as in PyProcessMacro the spotlight values of the moderators are defined as follow:
244
+ * By default, the spotlight values are equal to M - 1SD, M and M + 1SD, where M and SD are the mean and standard
245
+ deviation of that variable. If the option `quantile=1` is specified, then the spotlight values for each moderator
246
+ are the 10th, 25th, 50th, 75th and 90th percentile of that variable.
247
+ * If a moderator is a discrete variable, the spotlight values are those discrete values.
248
+
249
+ In Process, custom spotlight values can be applied to each moderator q, v, z, ... through the arguments qmodval,
250
+ vmodval, zmodval...
251
+
252
+ In PyProcessMacro, the user must instead supply custom values for each moderator in a dictionary
253
+ passed to the `modval` parameter:
254
+
255
+ ````python
256
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
257
+ m=["MediationSkills", "ModerationSkills"],
258
+ modval={
259
+ "Motivation":[-5, 0, 5], # Moderator 'Motivation' at values -5, 0 and 5
260
+ "SkillRelevance":[-1, 1] # Moderator 'SkillRelevance' at values -1 and 1
261
+ })
262
+ p.summary()
263
+ ````
264
+
265
+ ### E. Suppress the initialization information
266
+
267
+ When the Process object is initialized by Python, it displays various information about the model (model number, list of
268
+ variables, sample size, number of bootstrap samples, etc...). If you wish not to display this information, just add the
269
+ argument `suppr_init=True` when initializing the model.
270
+
271
+ ````python
272
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
273
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
274
+ p.summary()
275
+ ````
276
+
277
+ ## 2. Accessing the estimation results
278
+
279
+ After the `Process` object is initialized, you are not limited to printing the summary. PyProcessMacro implements the
280
+ following methods that allow you to conveniently recover the different estimates of interest:
281
+
282
+ ### A. `summary()`
283
+
284
+ This method replicates the output that you would see in Process, and displays the following information:
285
+ * Model summaries and parameters estimates for all outcomes (i.e. the independent variable, and the mediator(s)).
286
+ * If the model has a moderation, conditional effects at the spotlight values of the moderator(s).
287
+ * If the model has a mediation, direct and indirect effects.
288
+ * If the model has a moderation and a mediation, conditional direct and indirect effects at values of the moderator(s).
289
+ * If those statistics are relevant, indices for partial, conditional, and moderated moderated mediation will be
290
+ reported.
291
+
292
+ ### B. `outcome_models`
293
+
294
+ This command gives you individual access to each of the outcome models through a dictionary. This allows you to recover
295
+ the model and parameters estimates for each outcome.
296
+
297
+ Each OutcomeModel object has the following methods:
298
+ * `summary()` prints the full summary of the model (as Process does).
299
+ * `model_summary()` returns a DataFrame of goodness-of-fit statistics for the model.
300
+ * `coeff_summary()` returns a DataFrame of estimate, standard error, corresponding z/t, p-value, and
301
+ confidence interval for each of the parameters in the model.
302
+ * `estimation_results` gives you access to a dictionary containing all the statistical information of the
303
+ model.
304
+
305
+ ````python
306
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
307
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
308
+
309
+ model_medskills = p.outcome_models["MediationSkills"] # The model for the outcome "MediationSkills"
310
+
311
+ model_medskills.summary() # Print the summary for this model
312
+
313
+ df_params_med1 = model_medskills.coeff_summary() # Store the DataFrame of estimates into a variable.
314
+
315
+ med1_R2 = model_medskills.estimation_results["R2"] # Store the R² of the model into a variable.
316
+ ````
317
+
318
+ Note that the methods are called from the `model_medskills` object! If you call `p.coeff_summary()`,
319
+ you will get an error.
320
+
321
+ ### C. `direct_model`
322
+
323
+ When the Process model includes a mediation, the direct effect model can conveniently be accessed, which
324
+ gives you access to the following methods:
325
+
326
+ * `summary()` prints the full summary of the direct effects, as done in calling Process.summary().
327
+ * `coeff_summary()` returns a DataFrame of estimate, standard error, t-value, p-value, and confidence
328
+ interval for each of the (conditional) direct effect(s).
329
+
330
+ ````python
331
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
332
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
333
+
334
+ direct_model = p.direct_model # The model for the direct effect
335
+
336
+ df_params_direct = direct_model.coeff_summary() # Store the DataFrame of estimates into a variable.
337
+ ````
338
+
339
+ Note that the methods are called from the `direct_model` object! If you call `p.coeff_summary()`, you will get an
340
+ error.
341
+
342
+
343
+ ### D. `indirect_model`
344
+
345
+ When the Process model includes a parallel mediation, the indirect effect model can be accessed as well, which
346
+ gives you access to the following methods:
347
+
348
+ * `summary()` prints the full summary of the indirect effects, and other related indices, as done in
349
+ calling Process.summary().
350
+ * `coeff_summary()` returns a DataFrame of indirect effect(s) and their SE/CI for each of the mediation
351
+ paths
352
+ * `MM_index_summary()` returns a DataFrame of indices for Moderated Mediation, and their
353
+ SE/CI, for each of the mediation paths. If the model does not compute a MM, this will return an error.
354
+ * `PMM_index_summary()` returns a DataFrame of indices for Partial Moderated Mediation, and their
355
+ SE/CI, for each of the moderators and mediation paths. If the model does not compute a PMM, this will return an error.
356
+ * `CMM_index_summary()` returns a DataFrame of indices for Conditional Moderated Mediation, and their
357
+ SE/CI, for each of the moderators and mediation paths. If the model does not compute a CMM, this will return an error.
358
+ * `MMM_index_summary()` returns a DataFrame of indices for Moderated Moderated Mediation, and their
359
+ SE/CI, for each of the mediation paths. If the model does not compute a MMM, this will return an error.
360
+
361
+ ````python
362
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
363
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
364
+
365
+ indirect_model = p.indirect_model # The model for the direct effect
366
+
367
+ df_params_direct = indirect_model.coeff_summary() # Store the DataFrame of estimates into a variable.
368
+ ````
369
+
370
+ Note that the methods are called from the `indirect_model` object! If you call `p.coeff_summary()`, you will get an
371
+ error.
372
+
373
+
374
+ ## 3. Spotlight and Floodlight Analysis
375
+
376
+ ### A. Compute direct/indirect effects for specific values (spotlight analysis)
377
+
378
+ If you wish to display the conditional effects at other values of the moderator(s), you do not have to re-instantiate
379
+ the model from scratch, and can instead use the `spotlight_direct_effect()` and
380
+ `spotlight_indirect_effect()` methods.
381
+
382
+ ````python
383
+ df_direct_effects = p.spotlight_direct_effect(modval={
384
+ "Motivation":[-1, 0, 1], # Moderator 'Motivation' at values -1, 0 and 1
385
+ "SkillRelevance":[-5, 5] # Moderator 'SkillRelevance' at values -1 and 1
386
+ })
387
+
388
+ df_indirect_effects = p.spotlight_indirect_effect(med_name="MediationSkills", modval={
389
+ "Motivation":[-1, 0, 1], # Moderator 'Motivation' at values -1, 0 and 1
390
+ "SkillRelevance":[-5, 5] # Moderator 'SkillRelevance' at values -1 and 1
391
+ })
392
+ ````
393
+
394
+ ### B. Find the values of a moderator for which the direct/indirect effect are significant (floodlight analysis)
395
+
396
+ Instead of checking the direct and indirect effects at specific values, you might be interested in identifying under
397
+ which level of a moderator the effect becomes significant.
398
+
399
+ ````python
400
+ floodlight_motiv_direct= p.floodlight_direct_effect(mod_name="Motivation")
401
+ floodlight_motiv_indirect = p.floodlight_indirect_effect(med_name="MediationSkills", mod_name="Motivation")
402
+ ````
403
+
404
+ Calling `floodlight_motiv_direct` or `floodlight_motiv_indirect` will print out a detailed summary of the region(s) of
405
+ significance. Alternatively, you can call `floodlight_motiv_direct.get_significance_regions()` to get the regions of
406
+ positive/negative significance in a dictionary.
407
+
408
+ The floodlight analysis can only be conducted on one moderator at a time. When multiple moderators are present on the
409
+ direct/indirect path, the floodlight analysis assumes the value of those other moderators to be zero. However, you can
410
+ change this behavior by specifying a custom level for the other moderators:
411
+
412
+ ````python
413
+ floodlight_motiv_direct= p.floodlight_direct_effect(mod_name="Motivation", other_modval={"SkillRelevance": 1})
414
+ floodlight_motiv_indirect = p.floodlight_indirect_effect(med_name="MediationSkills", mod_name="Motivation",
415
+ other_modval={"SkillRelevance": 1})
416
+ ````
417
+
418
+ Here, pyprocessmacro will conduct a floodlight analysis on the effect of MediationSkills when the level of
419
+ SkillRelevance is set to 1. This is, in essence, a spotlight-floodlight analysis ;).
420
+
421
+
422
+ ## 4. Recover bootstrap samples estimates
423
+
424
+ The original Process macro allows you to save the parameter estimates for each bootstrap sample by specifying the `save`
425
+ keyword. The Macro then returns a new dataset of bootstrap estimates.
426
+
427
+ In PyProcessMacro, this is done by calling the method `get_bootstrap_estimates()`, which returns a DataFrame containing
428
+ the parameters estimates for all variables in the model, for each outcome.
429
+
430
+ ````python
431
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
432
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
433
+
434
+ boot_estimates = p.get_bootstrap_estimates() # Called from the Process object directly.
435
+ ````
436
+
437
+ ## 5. Plotting capabilities
438
+
439
+ PyProcessMacro allows you to plot the conditional direct and indirect effect(s), at different values of the moderators.
440
+
441
+ The methods `plot_conditional_indirect_effects()` and `plot_conditional_direct_effects()` are identical in syntax,
442
+ with one small exception: you must specify the name of the mediator for `plot_conditional_indirect_effects` as a first argument.
443
+ They return a `seaborn.FacetGrid` object that can be used to further tweak the appearance of the plot.
444
+
445
+ ### A. Basic Usage
446
+
447
+ When plotting conditional direct (and indirect) effects, the effect is always represented on the y-axis.
448
+
449
+ The various spotlight values of the moderator(s) can be represented on several dimensions:
450
+ * On the x-axis (moderator passed to `x`).
451
+ * As a color-code, in which case several lines are displayed on the same plot (moderator passed to `hue`).
452
+ * On different plots, displayed side-by-side (moderator passed to `col`).
453
+ * On different plots, displayed one below the other (moderator passed to `row`)
454
+
455
+ At the minimum, the `x` argument is required, while the `hue`, `col` and `row` are optional.
456
+ The examples below are showing what the plots could look like for a model with two moderators.
457
+
458
+ ````python
459
+ from pyprocessmacro import Process
460
+ import pandas as pd
461
+ import matplotlib.pyplot as plt
462
+
463
+ df = pd.read_csv("MyDataset.csv")
464
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
465
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
466
+
467
+ # Conditional direct effects of Effort, at values of Motivation (x-axis)
468
+ g = p.plot_conditional_direct_effects(x="Motivation")
469
+ plt.show()
470
+ ````
471
+ ![BasicExample](images/Ex1.png)
472
+
473
+ ````python
474
+ # Conditional indirect effects through MediationSkills, at values of Motivation (x-axis) and
475
+ # SkillRelevance (color-coded)
476
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", hue="SkillRelevance")
477
+ g.add_legend(title="") # Add the legend for the color-coding
478
+ plt.show()
479
+ ````
480
+ ![ColorCodedModerator](images/Ex2.png)
481
+ ````python
482
+ # Display the values for SkillRelevance on side-by-side plots instead.
483
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", col="SkillRelevance")
484
+ plt.show()
485
+ ````
486
+ ![ColCodedModerator](images/Ex3.png)
487
+ ````python
488
+ # Display the values for SkillRelevance on vertical plots instead.
489
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", row="SkillRelevance")
490
+ plt.show()
491
+ ````
492
+ ![RowCodedModerator](images/Ex4.png)
493
+ ### B. Change the spotlight values
494
+
495
+ By default, the spotlight values used to plot the effects are the same as the ones passed when initializing Process.
496
+ However, you can pass custom values for some, or all, the moderators through the `modval` argument.
497
+
498
+ ````python
499
+ # Change the spotlight values for SkillRelevance
500
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", hue="SkillRelevance",
501
+ modval={"SkillRelevance": [-5, 5]})
502
+ g.add_legend(title="")
503
+ plt.show()
504
+ ````
505
+ ![ChangeSpotValues](images/Ex6.png)
506
+
507
+ ### C. Representation of uncertainty
508
+
509
+ The display of confidence intervals for the direct/indirect effects can be customized through the `errstyle` argument:
510
+ * `errstyle="band"` (default) plots a continuous error band between the lower and higher confidence interval. This
511
+ representation works well when the moderator displayed on the x-axis is continuous (e.g. age), as it allows you to
512
+ visualize the error at all levels of the moderator.
513
+ * `errstyle="ci"` plots an error bar at each value of the moderator on x-axis. It works well when the moderator
514
+ displayed on the x-axis is dichotomous or has few values (e.g. gender), as it reduces clutter.
515
+ * `errstyle="none"` does not show the error on the plot.
516
+
517
+ ````python
518
+ # CI for dichotomous moderator
519
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", hue="SkillRelevance",
520
+ modval={"Motivation": [0, 1], "SkillRelevance":[-1, 0, 1]},
521
+ errstyle="ci")
522
+ ````
523
+ ![ErrStyleCI](images/Ex7.png)
524
+
525
+ ````python
526
+ # Error band for continous moderator
527
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", hue="SkillRelevance",
528
+ modval={"SkillRelevance":[-1, 0, 1]},
529
+ errstyle="ci")
530
+ ````
531
+ ![ErrStyleBand](images/Ex8.png)
532
+ ````python
533
+ # No representation of error
534
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", hue="SkillRelevance",
535
+ modval={"SkillRelevance":[-1, 0, 1]},
536
+ errstyle="none")
537
+
538
+ plt.show()
539
+ ````
540
+ ![ErrStyleNone](images/Ex9.png)
541
+
542
+
543
+ ### D. "Partial" plots
544
+
545
+ So far, the number of moderators supplied as arguments to the plot function was always equal to the number of moderators
546
+ on the path of interest (1 for the direct path, 2 for the indirect path).
547
+
548
+ You can also "omit" some moderators, and plot "partial" conditional direct/indirect effects. In that case, the omitted
549
+ moderators will assume a value of 0 when computing the direct/indirect effects. To make sure that this is intentional,
550
+ pyprocessmacro will warn you when this happens.
551
+
552
+ ````python
553
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
554
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
555
+
556
+ # SkillRelevance is a moderator of the indirect path, but is not mentioned as an argument in the plotting function!
557
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation")
558
+ plt.show() # This plot represents the "partial" conditional indirect effect, when SkillRelevance is evaluated at 0.
559
+ ````
560
+ ![PartialPlotDefault](images/Ex10.png)
561
+
562
+
563
+ If you want the omitted moderator(s) to have a different value than 0, you must pass a unique value for each moderator
564
+ as a key in the `modval` dictionary:
565
+
566
+ ````python
567
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", modval={"SkillRelevance":[-5]})
568
+ plt.show() # This plot represents the "partial" conditional indirect effect, when SkillRelevance is evaluated at -5.
569
+ ````
570
+ ![PartialPlotCustom](images/Ex11.png)
571
+
572
+ If you pass multiple values in `modval` for a moderator that is not displayed of the graph, the method will
573
+ return an error.
574
+
575
+ ### E. Customize the appearance of the plots
576
+
577
+ Under the hood, the plotting functions relies on a `seaborn.FacetGrid` object, on which the following objects
578
+ are plotted:
579
+ * `plt.plot` when `errstyle="none"`
580
+ * `plt.plot` and `plt.fill_between` when `errstyle="band"`
581
+ * `plt.plot` and `plt.errorbar` when `errstyle="ci"`
582
+
583
+ You can pass custom arguments to each of those objects to customize the appearance of the plot:
584
+
585
+ ````python
586
+ from pyprocessmacro import Process
587
+ import pandas as pd
588
+ import matplotlib.pyplot as plt
589
+
590
+ df = pd.read_csv("MyDataset.csv")
591
+ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="SkillRelevance",
592
+ m=["MediationSkills", "ModerationSkills"], suppr_init=True)
593
+
594
+ plot_kws = {'lw': 5} # Plot: Make the lines bolder
595
+ err_kws = {'capthick': 5, 'ecolor': 'black', 'elinewidth': 5, 'capsize': 5} # Errors: Make the CI bolder and black
596
+ facet_kws = {'aspect': 1} #Grid: Make the FacetGrid a square rather than a rectangle
597
+
598
+
599
+ g = p.plot_conditional_indirect_effects(med_name="MediationSkills", x="Motivation", errstyle="ci",
600
+ plot_kws=plot_kws, err_kws=err_kws, facet_kws=facet_kws)
601
+ ````
602
+ ![PlotCustomKws](images/Ex12.png)
603
+
604
+ # 7. About
605
+ PyProcessMacro was developed by Quentin André during his PhD in Marketing at INSEAD Business School, France.
606
+
607
+ His work on this library was made possible by Andrew F. Hayes'
608
+ [excellent book](http://afhayes.com/introduction-to-mediation-moderation-and-conditional-process-analysis.html),
609
+ by the financial support of INSEAD and by the ADLPartner PhD award.
610
+
611
+