PyProcessMacro 1.0.14__tar.gz → 2.0.0__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.
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PKG-INFO +48 -3
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PyProcessMacro.egg-info/PKG-INFO +48 -3
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PyProcessMacro.egg-info/SOURCES.txt +1 -4
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PyProcessMacro.egg-info/requires.txt +1 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/README.md +46 -2
- pyprocessmacro-2.0.0/pyprocessmacro/__init__.py +10 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/pyprocessmacro/models.py +42 -18
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/pyprocessmacro/process.py +87 -43
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/pyprocessmacro/utils.py +29 -13
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/pyproject.toml +1 -1
- pyprocessmacro-1.0.14/pyprocessmacro/__init__.py +0 -9
- pyprocessmacro-1.0.14/pyprocessmacro/models.pyi +0 -228
- pyprocessmacro-1.0.14/pyprocessmacro/process.pyi +0 -163
- pyprocessmacro-1.0.14/pyprocessmacro/utils.pyi +0 -92
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/LICENSE.txt +0 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/MANIFEST.in +0 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PyProcessMacro.egg-info/dependency_links.txt +0 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/PyProcessMacro.egg-info/top_level.txt +0 -0
- {pyprocessmacro-1.0.14 → pyprocessmacro-2.0.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyProcessMacro
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A Python library for moderation, mediation and conditional process analysis. Based on Andrew F. Hayes' Process Macro.
|
|
5
5
|
Author-email: Quentin André <quentin.andre@insead.edu>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -29,6 +29,7 @@ Requires-Dist: matplotlib>=3.7
|
|
|
29
29
|
Requires-Dist: seaborn>=0.13
|
|
30
30
|
Provides-Extra: test
|
|
31
31
|
Requires-Dist: pytest>=8; extra == "test"
|
|
32
|
+
Requires-Dist: statsmodels>=0.14; extra == "test"
|
|
32
33
|
Dynamic: license-file
|
|
33
34
|
|
|
34
35
|
PyProcessMacro: A Python Implementation of Andrew F. Hayes' 'Process' Macro
|
|
@@ -68,7 +69,8 @@ In the current version, PyProcessMacro replicates the following features from th
|
|
|
68
69
|
* All statistics reported by Process:
|
|
69
70
|
* Variable parameters for outcome models
|
|
70
71
|
* (Conditional) direct and indirect effects
|
|
71
|
-
*
|
|
72
|
+
* The index of moderated mediation and, following PROCESS 3, the indices of partial, conditional and
|
|
73
|
+
moderated moderated mediation, whenever the indirect effect is linear in the moderator(s).
|
|
72
74
|
* Automatic generation of spotlight values for continuous/discrete moderators.
|
|
73
75
|
* Rich set of options to tweak the estimation and display of the different models: (almost) all the options from
|
|
74
76
|
Process exist in PyProcessMacro. Check the doc for more details.
|
|
@@ -94,6 +96,38 @@ In the current version, the following features have not yet been ported to PyPro
|
|
|
94
96
|
* Some options (`normal`, `varorder`, ...). PyProcessMacro will issue a warning to tell you if an option you are
|
|
95
97
|
trying to use is not implemented.
|
|
96
98
|
|
|
99
|
+
# Upgrading to 2.0
|
|
100
|
+
|
|
101
|
+
Version 2.0 corrects several statistics and tightens input handling. Reported numbers change in these ways:
|
|
102
|
+
|
|
103
|
+
* Confidence intervals of OLS coefficients and of (conditional) direct effects use t critical values with the
|
|
104
|
+
residual degrees of freedom, as PROCESS does. They were based on z, so they widen slightly; the difference is
|
|
105
|
+
visible in small samples.
|
|
106
|
+
* Adjusted R² of OLS outcome models is slightly higher: the previous value used one degree of freedom too many.
|
|
107
|
+
* Cox-Snell and Nagelkerke pseudo R² of logistic outcome models are finite for large samples instead of NaN.
|
|
108
|
+
* No index of moderated mediation is reported when a moderator sits on both the X-to-M and the M-to-Y paths
|
|
109
|
+
(models 58 to 73, 75 and 76), matching PROCESS: the indirect effect is not linear in such a moderator. The
|
|
110
|
+
`*_index_summary()` methods raise `NotImplementedError` for those models.
|
|
111
|
+
* The sample size reported after listwise deletion is the number of rows kept.
|
|
112
|
+
|
|
113
|
+
Behaviour that used to be silent now speaks up:
|
|
114
|
+
|
|
115
|
+
* A misspelled key in `modval`, or a keyword argument that is neither a variable nor an option, raises an error
|
|
116
|
+
instead of being ignored.
|
|
117
|
+
* Unsupported PROCESS options (`jn`, `effsize`, `mc`, `normal`, ...) raise a visible `UserWarning`.
|
|
118
|
+
* A logistic regression that does not converge raises `pyprocessmacro.ConvergenceError`. Bootstrap resamples
|
|
119
|
+
that fail are counted, and the bootstrap stops with an error if more resamples fail than were requested.
|
|
120
|
+
|
|
121
|
+
Removed and added:
|
|
122
|
+
|
|
123
|
+
* `plot_direct_effects()` and `plot_indirect_effects()` are removed; use `plot_conditional_direct_effects()`
|
|
124
|
+
and `plot_conditional_indirect_effects()`.
|
|
125
|
+
* `cov_type` selects the OLS covariance estimator (`"standard"`, `"HC0"`, `"HC1"`, `"HC2"` or `"HC3"`);
|
|
126
|
+
`hc3=True` remains as shorthand for `"HC3"`.
|
|
127
|
+
* `seed=None` draws a different bootstrap sample on every run, and `seed=0` is accepted.
|
|
128
|
+
* `Process.dv` names the outcome variable (`iv` is kept for compatibility).
|
|
129
|
+
* Python 3.11 or newer is required (since 1.0.14).
|
|
130
|
+
|
|
97
131
|
# Version History
|
|
98
132
|
|
|
99
133
|
## Master Versions
|
|
@@ -117,7 +151,7 @@ report and for the fix.
|
|
|
117
151
|
|
|
118
152
|
### 1.0.4
|
|
119
153
|
**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
|
|
154
|
+
PyProcessMacro was, by default, using the HC3 estimator for the variance-covariance matrix instead of the standard (non-robust) estimator.
|
|
121
155
|
This has now been changed. To continue using the HC3 estimator, specify `hc3=True` when initializing the Process instance.
|
|
122
156
|
Thanks to Zoé Ziani for the bug report.
|
|
123
157
|
|
|
@@ -274,6 +308,17 @@ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="Skill
|
|
|
274
308
|
p.summary()
|
|
275
309
|
````
|
|
276
310
|
|
|
311
|
+
### F. Choosing the covariance estimator
|
|
312
|
+
|
|
313
|
+
By default, the standard errors of the OLS outcome models use the standard (homoskedastic) estimator. The
|
|
314
|
+
`cov_type` argument selects a heteroskedasticity-consistent estimator instead: `"HC0"`, `"HC1"`, `"HC2"` or
|
|
315
|
+
`"HC3"`. `hc3=True` is shorthand for `cov_type="HC3"`, which is what the original Process macro uses when
|
|
316
|
+
`hc3=1` is specified. Logistic outcome models always use the inverse of the Hessian.
|
|
317
|
+
|
|
318
|
+
````python
|
|
319
|
+
p = Process(data=df, model=4, x="Effort", y="Success", m=["MediationSkills"], cov_type="HC3")
|
|
320
|
+
````
|
|
321
|
+
|
|
277
322
|
## 2. Accessing the estimation results
|
|
278
323
|
|
|
279
324
|
After the `Process` object is initialized, you are not limited to printing the summary. PyProcessMacro implements the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyProcessMacro
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A Python library for moderation, mediation and conditional process analysis. Based on Andrew F. Hayes' Process Macro.
|
|
5
5
|
Author-email: Quentin André <quentin.andre@insead.edu>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -29,6 +29,7 @@ Requires-Dist: matplotlib>=3.7
|
|
|
29
29
|
Requires-Dist: seaborn>=0.13
|
|
30
30
|
Provides-Extra: test
|
|
31
31
|
Requires-Dist: pytest>=8; extra == "test"
|
|
32
|
+
Requires-Dist: statsmodels>=0.14; extra == "test"
|
|
32
33
|
Dynamic: license-file
|
|
33
34
|
|
|
34
35
|
PyProcessMacro: A Python Implementation of Andrew F. Hayes' 'Process' Macro
|
|
@@ -68,7 +69,8 @@ In the current version, PyProcessMacro replicates the following features from th
|
|
|
68
69
|
* All statistics reported by Process:
|
|
69
70
|
* Variable parameters for outcome models
|
|
70
71
|
* (Conditional) direct and indirect effects
|
|
71
|
-
*
|
|
72
|
+
* The index of moderated mediation and, following PROCESS 3, the indices of partial, conditional and
|
|
73
|
+
moderated moderated mediation, whenever the indirect effect is linear in the moderator(s).
|
|
72
74
|
* Automatic generation of spotlight values for continuous/discrete moderators.
|
|
73
75
|
* Rich set of options to tweak the estimation and display of the different models: (almost) all the options from
|
|
74
76
|
Process exist in PyProcessMacro. Check the doc for more details.
|
|
@@ -94,6 +96,38 @@ In the current version, the following features have not yet been ported to PyPro
|
|
|
94
96
|
* Some options (`normal`, `varorder`, ...). PyProcessMacro will issue a warning to tell you if an option you are
|
|
95
97
|
trying to use is not implemented.
|
|
96
98
|
|
|
99
|
+
# Upgrading to 2.0
|
|
100
|
+
|
|
101
|
+
Version 2.0 corrects several statistics and tightens input handling. Reported numbers change in these ways:
|
|
102
|
+
|
|
103
|
+
* Confidence intervals of OLS coefficients and of (conditional) direct effects use t critical values with the
|
|
104
|
+
residual degrees of freedom, as PROCESS does. They were based on z, so they widen slightly; the difference is
|
|
105
|
+
visible in small samples.
|
|
106
|
+
* Adjusted R² of OLS outcome models is slightly higher: the previous value used one degree of freedom too many.
|
|
107
|
+
* Cox-Snell and Nagelkerke pseudo R² of logistic outcome models are finite for large samples instead of NaN.
|
|
108
|
+
* No index of moderated mediation is reported when a moderator sits on both the X-to-M and the M-to-Y paths
|
|
109
|
+
(models 58 to 73, 75 and 76), matching PROCESS: the indirect effect is not linear in such a moderator. The
|
|
110
|
+
`*_index_summary()` methods raise `NotImplementedError` for those models.
|
|
111
|
+
* The sample size reported after listwise deletion is the number of rows kept.
|
|
112
|
+
|
|
113
|
+
Behaviour that used to be silent now speaks up:
|
|
114
|
+
|
|
115
|
+
* A misspelled key in `modval`, or a keyword argument that is neither a variable nor an option, raises an error
|
|
116
|
+
instead of being ignored.
|
|
117
|
+
* Unsupported PROCESS options (`jn`, `effsize`, `mc`, `normal`, ...) raise a visible `UserWarning`.
|
|
118
|
+
* A logistic regression that does not converge raises `pyprocessmacro.ConvergenceError`. Bootstrap resamples
|
|
119
|
+
that fail are counted, and the bootstrap stops with an error if more resamples fail than were requested.
|
|
120
|
+
|
|
121
|
+
Removed and added:
|
|
122
|
+
|
|
123
|
+
* `plot_direct_effects()` and `plot_indirect_effects()` are removed; use `plot_conditional_direct_effects()`
|
|
124
|
+
and `plot_conditional_indirect_effects()`.
|
|
125
|
+
* `cov_type` selects the OLS covariance estimator (`"standard"`, `"HC0"`, `"HC1"`, `"HC2"` or `"HC3"`);
|
|
126
|
+
`hc3=True` remains as shorthand for `"HC3"`.
|
|
127
|
+
* `seed=None` draws a different bootstrap sample on every run, and `seed=0` is accepted.
|
|
128
|
+
* `Process.dv` names the outcome variable (`iv` is kept for compatibility).
|
|
129
|
+
* Python 3.11 or newer is required (since 1.0.14).
|
|
130
|
+
|
|
97
131
|
# Version History
|
|
98
132
|
|
|
99
133
|
## Master Versions
|
|
@@ -117,7 +151,7 @@ report and for the fix.
|
|
|
117
151
|
|
|
118
152
|
### 1.0.4
|
|
119
153
|
**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
|
|
154
|
+
PyProcessMacro was, by default, using the HC3 estimator for the variance-covariance matrix instead of the standard (non-robust) estimator.
|
|
121
155
|
This has now been changed. To continue using the HC3 estimator, specify `hc3=True` when initializing the Process instance.
|
|
122
156
|
Thanks to Zoé Ziani for the bug report.
|
|
123
157
|
|
|
@@ -274,6 +308,17 @@ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="Skill
|
|
|
274
308
|
p.summary()
|
|
275
309
|
````
|
|
276
310
|
|
|
311
|
+
### F. Choosing the covariance estimator
|
|
312
|
+
|
|
313
|
+
By default, the standard errors of the OLS outcome models use the standard (homoskedastic) estimator. The
|
|
314
|
+
`cov_type` argument selects a heteroskedasticity-consistent estimator instead: `"HC0"`, `"HC1"`, `"HC2"` or
|
|
315
|
+
`"HC3"`. `hc3=True` is shorthand for `cov_type="HC3"`, which is what the original Process macro uses when
|
|
316
|
+
`hc3=1` is specified. Logistic outcome models always use the inverse of the Hessian.
|
|
317
|
+
|
|
318
|
+
````python
|
|
319
|
+
p = Process(data=df, model=4, x="Effort", y="Success", m=["MediationSkills"], cov_type="HC3")
|
|
320
|
+
````
|
|
321
|
+
|
|
277
322
|
## 2. Accessing the estimation results
|
|
278
323
|
|
|
279
324
|
After the `Process` object is initialized, you are not limited to printing the summary. PyProcessMacro implements the
|
|
@@ -9,8 +9,5 @@ PyProcessMacro.egg-info/requires.txt
|
|
|
9
9
|
PyProcessMacro.egg-info/top_level.txt
|
|
10
10
|
pyprocessmacro/__init__.py
|
|
11
11
|
pyprocessmacro/models.py
|
|
12
|
-
pyprocessmacro/models.pyi
|
|
13
12
|
pyprocessmacro/process.py
|
|
14
|
-
pyprocessmacro/
|
|
15
|
-
pyprocessmacro/utils.py
|
|
16
|
-
pyprocessmacro/utils.pyi
|
|
13
|
+
pyprocessmacro/utils.py
|
|
@@ -35,7 +35,8 @@ In the current version, PyProcessMacro replicates the following features from th
|
|
|
35
35
|
* All statistics reported by Process:
|
|
36
36
|
* Variable parameters for outcome models
|
|
37
37
|
* (Conditional) direct and indirect effects
|
|
38
|
-
*
|
|
38
|
+
* The index of moderated mediation and, following PROCESS 3, the indices of partial, conditional and
|
|
39
|
+
moderated moderated mediation, whenever the indirect effect is linear in the moderator(s).
|
|
39
40
|
* Automatic generation of spotlight values for continuous/discrete moderators.
|
|
40
41
|
* Rich set of options to tweak the estimation and display of the different models: (almost) all the options from
|
|
41
42
|
Process exist in PyProcessMacro. Check the doc for more details.
|
|
@@ -61,6 +62,38 @@ In the current version, the following features have not yet been ported to PyPro
|
|
|
61
62
|
* Some options (`normal`, `varorder`, ...). PyProcessMacro will issue a warning to tell you if an option you are
|
|
62
63
|
trying to use is not implemented.
|
|
63
64
|
|
|
65
|
+
# Upgrading to 2.0
|
|
66
|
+
|
|
67
|
+
Version 2.0 corrects several statistics and tightens input handling. Reported numbers change in these ways:
|
|
68
|
+
|
|
69
|
+
* Confidence intervals of OLS coefficients and of (conditional) direct effects use t critical values with the
|
|
70
|
+
residual degrees of freedom, as PROCESS does. They were based on z, so they widen slightly; the difference is
|
|
71
|
+
visible in small samples.
|
|
72
|
+
* Adjusted R² of OLS outcome models is slightly higher: the previous value used one degree of freedom too many.
|
|
73
|
+
* Cox-Snell and Nagelkerke pseudo R² of logistic outcome models are finite for large samples instead of NaN.
|
|
74
|
+
* No index of moderated mediation is reported when a moderator sits on both the X-to-M and the M-to-Y paths
|
|
75
|
+
(models 58 to 73, 75 and 76), matching PROCESS: the indirect effect is not linear in such a moderator. The
|
|
76
|
+
`*_index_summary()` methods raise `NotImplementedError` for those models.
|
|
77
|
+
* The sample size reported after listwise deletion is the number of rows kept.
|
|
78
|
+
|
|
79
|
+
Behaviour that used to be silent now speaks up:
|
|
80
|
+
|
|
81
|
+
* A misspelled key in `modval`, or a keyword argument that is neither a variable nor an option, raises an error
|
|
82
|
+
instead of being ignored.
|
|
83
|
+
* Unsupported PROCESS options (`jn`, `effsize`, `mc`, `normal`, ...) raise a visible `UserWarning`.
|
|
84
|
+
* A logistic regression that does not converge raises `pyprocessmacro.ConvergenceError`. Bootstrap resamples
|
|
85
|
+
that fail are counted, and the bootstrap stops with an error if more resamples fail than were requested.
|
|
86
|
+
|
|
87
|
+
Removed and added:
|
|
88
|
+
|
|
89
|
+
* `plot_direct_effects()` and `plot_indirect_effects()` are removed; use `plot_conditional_direct_effects()`
|
|
90
|
+
and `plot_conditional_indirect_effects()`.
|
|
91
|
+
* `cov_type` selects the OLS covariance estimator (`"standard"`, `"HC0"`, `"HC1"`, `"HC2"` or `"HC3"`);
|
|
92
|
+
`hc3=True` remains as shorthand for `"HC3"`.
|
|
93
|
+
* `seed=None` draws a different bootstrap sample on every run, and `seed=0` is accepted.
|
|
94
|
+
* `Process.dv` names the outcome variable (`iv` is kept for compatibility).
|
|
95
|
+
* Python 3.11 or newer is required (since 1.0.14).
|
|
96
|
+
|
|
64
97
|
# Version History
|
|
65
98
|
|
|
66
99
|
## Master Versions
|
|
@@ -84,7 +117,7 @@ report and for the fix.
|
|
|
84
117
|
|
|
85
118
|
### 1.0.4
|
|
86
119
|
**Bug fix for standard error estimate in all models**
|
|
87
|
-
PyProcessMacro was, by default, using the HC3 estimator for the variance-covariance matrix instead of the
|
|
120
|
+
PyProcessMacro was, by default, using the HC3 estimator for the variance-covariance matrix instead of the standard (non-robust) estimator.
|
|
88
121
|
This has now been changed. To continue using the HC3 estimator, specify `hc3=True` when initializing the Process instance.
|
|
89
122
|
Thanks to Zoé Ziani for the bug report.
|
|
90
123
|
|
|
@@ -241,6 +274,17 @@ p = Process(data=df, model=13, x="Effort", y="Success", w="Motivation", z="Skill
|
|
|
241
274
|
p.summary()
|
|
242
275
|
````
|
|
243
276
|
|
|
277
|
+
### F. Choosing the covariance estimator
|
|
278
|
+
|
|
279
|
+
By default, the standard errors of the OLS outcome models use the standard (homoskedastic) estimator. The
|
|
280
|
+
`cov_type` argument selects a heteroskedasticity-consistent estimator instead: `"HC0"`, `"HC1"`, `"HC2"` or
|
|
281
|
+
`"HC3"`. `hc3=True` is shorthand for `cov_type="HC3"`, which is what the original Process macro uses when
|
|
282
|
+
`hc3=1` is specified. Logistic outcome models always use the inverse of the Hessian.
|
|
283
|
+
|
|
284
|
+
````python
|
|
285
|
+
p = Process(data=df, model=4, x="Effort", y="Success", m=["MediationSkills"], cov_type="HC3")
|
|
286
|
+
````
|
|
287
|
+
|
|
244
288
|
## 2. Accessing the estimation results
|
|
245
289
|
|
|
246
290
|
After the `Process` object is initialized, you are not limited to printing the summary. PyProcessMacro implements the
|
|
@@ -16,8 +16,10 @@ from .utils import (
|
|
|
16
16
|
eval_expression,
|
|
17
17
|
bias_corrected_ci,
|
|
18
18
|
z_score,
|
|
19
|
+
t_score,
|
|
19
20
|
percentile_ci,
|
|
20
21
|
find_significance_region,
|
|
22
|
+
ConvergenceError,
|
|
21
23
|
)
|
|
22
24
|
|
|
23
25
|
|
|
@@ -103,14 +105,26 @@ class BaseLogit(object):
|
|
|
103
105
|
return -self._hessian(params) / self._n_obs
|
|
104
106
|
|
|
105
107
|
oldparams = np.inf
|
|
106
|
-
newparams = np.
|
|
108
|
+
newparams = np.zeros(self._n_vars)
|
|
107
109
|
while iterations < max_iter and np.any(
|
|
108
110
|
np.abs(newparams - oldparams) > tolerance
|
|
109
111
|
):
|
|
110
112
|
oldparams = newparams
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
try:
|
|
114
|
+
H = hess(oldparams)
|
|
115
|
+
newparams = oldparams - dot(inv(H), score(oldparams))
|
|
116
|
+
except LinAlgError:
|
|
117
|
+
raise ConvergenceError("The Hessian of the logistic regression is singular.")
|
|
113
118
|
iterations += 1
|
|
119
|
+
if not np.all(np.isfinite(newparams)):
|
|
120
|
+
raise ConvergenceError(
|
|
121
|
+
"The logistic regression diverged (the outcome may be perfectly separated)."
|
|
122
|
+
)
|
|
123
|
+
if np.any(np.abs(newparams - oldparams) > tolerance):
|
|
124
|
+
raise ConvergenceError(
|
|
125
|
+
f"The logistic regression did not converge in {max_iter} iterations "
|
|
126
|
+
"(increase 'iterate', relax 'convergence', or check the outcome for separation)."
|
|
127
|
+
)
|
|
114
128
|
return newparams
|
|
115
129
|
|
|
116
130
|
|
|
@@ -286,7 +300,7 @@ class OLSOutcomeModel(BaseOutcomeModel):
|
|
|
286
300
|
resid = y - dot(x, betas)
|
|
287
301
|
mse = (resid ** 2).sum() / df_e
|
|
288
302
|
sse = dot(resid.T, resid) / df_e
|
|
289
|
-
errortype = "
|
|
303
|
+
errortype = self._options.get("cov_type") or ("HC3" if self._options.get("hc3") else "standard")
|
|
290
304
|
if errortype == "standard":
|
|
291
305
|
vcv = np.true_divide(1, n_obs - n_vars) * dot(resid.T, resid) * inv_xx
|
|
292
306
|
elif errortype == "HC0":
|
|
@@ -294,7 +308,7 @@ class OLSOutcomeModel(BaseOutcomeModel):
|
|
|
294
308
|
vcv = dot(dot(dot(inv_xx, x.T) * sq_resid, x), inv_xx)
|
|
295
309
|
elif errortype == "HC1":
|
|
296
310
|
sq_resid = (resid ** 2).squeeze()
|
|
297
|
-
vcv = np.true_divide(n_obs, n_obs - n_vars
|
|
311
|
+
vcv = np.true_divide(n_obs, n_obs - n_vars) * dot( # n_vars counts the constant (#52)
|
|
298
312
|
dot(dot(inv_xx, x.T) * sq_resid, x), inv_xx
|
|
299
313
|
)
|
|
300
314
|
elif errortype == "HC2":
|
|
@@ -316,13 +330,13 @@ class OLSOutcomeModel(BaseOutcomeModel):
|
|
|
316
330
|
t = betas / se
|
|
317
331
|
p = stats.t.sf(np.abs(t), df_e) * 2
|
|
318
332
|
conf = self._options["conf"]
|
|
319
|
-
|
|
333
|
+
tcrit = t_score(conf, df_e) # OLS intervals use the t distribution, as PROCESS does (#40)
|
|
320
334
|
R2 = 1 - resid.var() / y.var()
|
|
321
|
-
adjR2 = 1 - (1 - R2) * ((n_obs - 1) /
|
|
335
|
+
adjR2 = 1 - (1 - R2) * ((n_obs - 1) / df_e) # n_vars already counts the constant (#41)
|
|
322
336
|
F = (R2 / df_r) / ((1 - R2) / df_e)
|
|
323
|
-
F_pval =
|
|
324
|
-
llci = betas - (se *
|
|
325
|
-
ulci = betas + (se *
|
|
337
|
+
F_pval = stats.f.sf(F, df_r, df_e)
|
|
338
|
+
llci = betas - (se * tcrit)
|
|
339
|
+
ulci = betas + (se * tcrit)
|
|
326
340
|
names = [self._symb_to_var.get(x, x) for x in self._exogvars]
|
|
327
341
|
estimation_results = {
|
|
328
342
|
"betas": betas,
|
|
@@ -418,19 +432,19 @@ class LogitOutcomeModel(BaseOutcomeModel, BaseLogit):
|
|
|
418
432
|
|
|
419
433
|
# GOF statistics
|
|
420
434
|
llmodel = self._loglike(betas)
|
|
421
|
-
lmodel = np.exp(llmodel)
|
|
422
435
|
minus2ll = -2 * llmodel
|
|
423
436
|
|
|
424
437
|
null_model = NullLogitModel(self._endog, self._options)
|
|
425
438
|
betas_null = null_model._optimize()
|
|
426
439
|
llnull = null_model._loglike(betas_null)
|
|
427
|
-
lnull = np.exp(llnull)
|
|
428
440
|
|
|
429
441
|
d = 2 * (llmodel - llnull)
|
|
430
442
|
pvalue = stats.chi2.sf(d, self._n_vars - 1)
|
|
431
443
|
mcfadden = 1 - llmodel / llnull
|
|
432
|
-
|
|
433
|
-
|
|
444
|
+
# Likelihood ratios are taken in log space: exp(llnull) underflows to 0 beyond about a
|
|
445
|
+
# thousand observations, which turned both pseudo R-squared into NaN (#42).
|
|
446
|
+
coxsnell = 1 - np.exp(2 * (llnull - llmodel) / self._n_obs)
|
|
447
|
+
nagelkerke = coxsnell / (1 - np.exp(2 * llnull / self._n_obs))
|
|
434
448
|
names = [self._symb_to_var.get(x, x) for x in self._exogvars]
|
|
435
449
|
estimation_results = {
|
|
436
450
|
"betas": betas,
|
|
@@ -650,6 +664,7 @@ class ParallelMediationModel(object):
|
|
|
650
664
|
boot_betas_y = np.empty((n_boots, len(self._exog_terms_y)))
|
|
651
665
|
boot_betas_m = np.empty((self._n_meds, n_boots, len(self._exog_terms_m)))
|
|
652
666
|
n_fail_samples = 0
|
|
667
|
+
max_failures = n_boots # give up once more resamples failed than were requested (#49)
|
|
653
668
|
boot_ind = 0
|
|
654
669
|
sampler = bootstrap_sampler(self._n_obs, seed)
|
|
655
670
|
while boot_ind < n_boots:
|
|
@@ -666,8 +681,14 @@ class ParallelMediationModel(object):
|
|
|
666
681
|
m_b = self._compute_betas_m(m_e, m_x)
|
|
667
682
|
boot_betas_m[j][boot_ind] = m_b
|
|
668
683
|
boot_ind += 1
|
|
669
|
-
except LinAlgError: # Hessian
|
|
684
|
+
except (LinAlgError, ConvergenceError): # X'X or the Hessian is singular, or the logit diverged
|
|
670
685
|
n_fail_samples += 1
|
|
686
|
+
if n_fail_samples > max_failures:
|
|
687
|
+
raise RuntimeError(
|
|
688
|
+
f"{n_fail_samples} bootstrap samples failed to estimate before {n_boots} succeeded. "
|
|
689
|
+
"The model is probably not estimable on resamples of this data (check for separation, "
|
|
690
|
+
"collinearity, or a very small sample)."
|
|
691
|
+
)
|
|
671
692
|
|
|
672
693
|
return boot_betas_y, boot_betas_m, n_fail_samples
|
|
673
694
|
|
|
@@ -1585,9 +1606,12 @@ class DirectEffectModel(object):
|
|
|
1585
1606
|
dot(grad, vcv), np.transpose(grad)
|
|
1586
1607
|
) # V(Grad(X)) = Grad(X).V(X).Grad'(X)
|
|
1587
1608
|
se = np.sqrt(var)
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1609
|
+
if self._is_logit:
|
|
1610
|
+
crit = z_score(conf)
|
|
1611
|
+
else: # OLS intervals use the t distribution, as PROCESS does (#40)
|
|
1612
|
+
crit = t_score(conf, self._model.estimation_results["df_e"])
|
|
1613
|
+
llci = betas - (se * crit)
|
|
1614
|
+
ulci = betas + (se * crit)
|
|
1591
1615
|
return betas, se, llci, ulci
|
|
1592
1616
|
|
|
1593
1617
|
def coeff_summary(self):
|
|
@@ -16,8 +16,6 @@ from .models import (
|
|
|
16
16
|
)
|
|
17
17
|
from .utils import plot_conditional_effects, gen_moderators
|
|
18
18
|
|
|
19
|
-
warnings.simplefilter("default")
|
|
20
|
-
|
|
21
19
|
|
|
22
20
|
class Process(object):
|
|
23
21
|
__var_kws__ = {"x", "m", "w", "z", "v", "q", "y"}
|
|
@@ -31,6 +29,7 @@ class Process(object):
|
|
|
31
29
|
"effsize",
|
|
32
30
|
"jn",
|
|
33
31
|
"hc3",
|
|
32
|
+
"cov_type",
|
|
34
33
|
"controls_in",
|
|
35
34
|
"total",
|
|
36
35
|
"center",
|
|
@@ -564,6 +563,7 @@ class Process(object):
|
|
|
564
563
|
effsize=False,
|
|
565
564
|
jn=False,
|
|
566
565
|
hc3=False,
|
|
566
|
+
cov_type="standard",
|
|
567
567
|
controls=None,
|
|
568
568
|
controls_in="all",
|
|
569
569
|
total=False,
|
|
@@ -601,7 +601,8 @@ class Process(object):
|
|
|
601
601
|
:param boot: int
|
|
602
602
|
The number of bootstrap repetitions for the estimation of the SE and CI in indirect effects.
|
|
603
603
|
:param seed: int
|
|
604
|
-
The seed
|
|
604
|
+
The seed of the bootstrap sampler: an integer between 0 and 2**32 - 1 for reproducible samples,
|
|
605
|
+
or None for a different draw on every run.
|
|
605
606
|
:param conf: int
|
|
606
607
|
A value between 51 and 99, representing the desired level of confidence for the confidence intervals
|
|
607
608
|
:param effsize: bool
|
|
@@ -610,6 +611,11 @@ class Process(object):
|
|
|
610
611
|
If True, the Johnson-Neymann region of significance will be reported.
|
|
611
612
|
:param hc3: bool
|
|
612
613
|
If True, the HC3 estimator will be used for the variance/covariance matrix of the parameters.
|
|
614
|
+
Shorthand for cov_type="HC3".
|
|
615
|
+
:param cov_type: "standard", "HC0", "HC1", "HC2" or "HC3"
|
|
616
|
+
The estimator of the variance/covariance matrix of the OLS parameters: the standard homoskedastic
|
|
617
|
+
estimator, or one of the heteroskedasticity-consistent estimators. Logistic outcome models always
|
|
618
|
+
use the inverse of the Hessian.
|
|
613
619
|
:param controls: list of string
|
|
614
620
|
A list of control variables to include to the model(s).
|
|
615
621
|
:param controls_in: "all", "x_to_m", "all_to_y"
|
|
@@ -642,55 +648,65 @@ class Process(object):
|
|
|
642
648
|
:param precision:
|
|
643
649
|
The number of decimal places to display in the summary of the model results.
|
|
644
650
|
"""
|
|
645
|
-
if
|
|
651
|
+
if mc:
|
|
646
652
|
warnings.warn(
|
|
647
|
-
"The argument 'mc' for Monte-Carlo
|
|
648
|
-
|
|
653
|
+
"The argument 'mc' for Monte-Carlo confidence intervals is not supported; "
|
|
654
|
+
"bootstrap confidence intervals are used.",
|
|
655
|
+
UserWarning,
|
|
656
|
+
stacklevel=2,
|
|
649
657
|
)
|
|
650
658
|
if kwargs.pop("normal", None):
|
|
651
659
|
warnings.warn(
|
|
652
660
|
"The argument 'normal' for normal theory tests is not supported. "
|
|
653
661
|
"Bootstrapped CI are recommended.",
|
|
654
|
-
|
|
662
|
+
UserWarning,
|
|
663
|
+
stacklevel=2,
|
|
655
664
|
)
|
|
656
665
|
if kwargs.pop("varorder", None):
|
|
657
666
|
warnings.warn(
|
|
658
667
|
"The argument 'varorder' for normal theory tests is not supported. "
|
|
659
668
|
"Bootstrapped CI are recommended.",
|
|
660
|
-
|
|
669
|
+
UserWarning,
|
|
670
|
+
stacklevel=2,
|
|
661
671
|
)
|
|
662
672
|
if kwargs.pop("varlist", None):
|
|
663
673
|
warnings.warn(
|
|
664
674
|
"The 'varlist' is not required. To specify controls, use the 'controls' arguments",
|
|
665
|
-
|
|
675
|
+
UserWarning,
|
|
676
|
+
stacklevel=2,
|
|
666
677
|
)
|
|
667
678
|
if kwargs.pop("coeffci", None):
|
|
668
679
|
warnings.warn(
|
|
669
|
-
"The argument 'coeffci' is not supported.",
|
|
680
|
+
"The argument 'coeffci' is not supported.",
|
|
681
|
+
UserWarning,
|
|
682
|
+
stacklevel=2,
|
|
670
683
|
)
|
|
671
684
|
if kwargs.pop("plot", None):
|
|
672
685
|
warnings.warn(
|
|
673
686
|
"The argument 'plot' is not supported. Check the 'plot_conditional_direct_effects() and"
|
|
674
687
|
"'plot_conditional_indirect_effects()' methods instead.",
|
|
675
|
-
|
|
688
|
+
UserWarning,
|
|
689
|
+
stacklevel=2,
|
|
676
690
|
)
|
|
677
691
|
if kwargs.pop("save", None):
|
|
678
692
|
warnings.warn(
|
|
679
693
|
"The argument 'save' is not supported. Call the 'get_bootstrap_estimates() method to recover"
|
|
680
694
|
"the bootstrap samples instead.",
|
|
681
|
-
|
|
695
|
+
UserWarning,
|
|
696
|
+
stacklevel=2,
|
|
682
697
|
)
|
|
683
|
-
if
|
|
698
|
+
if effsize:
|
|
684
699
|
warnings.warn(
|
|
685
|
-
"The argument 'effsize' for effect sizes is not supported
|
|
686
|
-
|
|
687
|
-
|
|
700
|
+
"The argument 'effsize' for effect sizes is not supported and is ignored.",
|
|
701
|
+
UserWarning,
|
|
702
|
+
stacklevel=2,
|
|
688
703
|
)
|
|
689
|
-
if
|
|
704
|
+
if jn:
|
|
690
705
|
warnings.warn(
|
|
691
|
-
"The argument 'jn' for the Johnson-Neyman region of significance is not supported
|
|
692
|
-
"Call the 'floodlight_direct_effect()' and 'floodlight_indirect_effect()' methods instead.",
|
|
693
|
-
|
|
706
|
+
"The argument 'jn' for the Johnson-Neyman region of significance is not supported and is "
|
|
707
|
+
"ignored. Call the 'floodlight_direct_effect()' and 'floodlight_indirect_effect()' methods instead.",
|
|
708
|
+
UserWarning,
|
|
709
|
+
stacklevel=2,
|
|
694
710
|
)
|
|
695
711
|
|
|
696
712
|
if model == 6:
|
|
@@ -720,6 +736,12 @@ class Process(object):
|
|
|
720
736
|
|
|
721
737
|
# Check the congruence between the model specifications, the model number, and the data, and store the final
|
|
722
738
|
# list of variables used
|
|
739
|
+
unknown_kwargs = set(kwargs) - self.__var_kws__
|
|
740
|
+
if unknown_kwargs:
|
|
741
|
+
raise TypeError(
|
|
742
|
+
f"Process() got unexpected keyword argument(s): {', '.join(sorted(unknown_kwargs))}. "
|
|
743
|
+
"Variables are x, y, m, w, z, v and q; check the spelling of the options."
|
|
744
|
+
)
|
|
723
745
|
var_kwargs = {k: v for k, v in kwargs.items() if k in self.__var_kws__}
|
|
724
746
|
|
|
725
747
|
# _gen_valid_varlist normalizes every variable argument to a list, so the mediator and
|
|
@@ -763,7 +785,8 @@ class Process(object):
|
|
|
763
785
|
self.outcome_models = self._gen_outcome_models()
|
|
764
786
|
|
|
765
787
|
# Rename the dictionary of custom spotlight values, and generating the spotlight values.
|
|
766
|
-
|
|
788
|
+
self._check_moderator_names(modval, "modval")
|
|
789
|
+
modval_symb = {self._var_to_symb[k]: v for k, v in modval.items()}
|
|
767
790
|
self._spotlight_values = self._gen_spotlight_values(modval_symb)
|
|
768
791
|
|
|
769
792
|
# Generate the direct model.
|
|
@@ -779,6 +802,20 @@ class Process(object):
|
|
|
779
802
|
if not suppr_init:
|
|
780
803
|
self._print_init()
|
|
781
804
|
|
|
805
|
+
def _check_moderator_names(self, names, argument):
|
|
806
|
+
"""
|
|
807
|
+
Raise a ValueError if any of the names is not a moderator of the model (#46).
|
|
808
|
+
:param names: iterable of variable names
|
|
809
|
+
:param argument: the name of the argument being validated, for the error message
|
|
810
|
+
"""
|
|
811
|
+
moderators = {self._symb_to_var[s] for s in self._moderators["all"]}
|
|
812
|
+
unknown = [str(n) for n in names if n not in moderators]
|
|
813
|
+
if unknown:
|
|
814
|
+
raise ValueError(
|
|
815
|
+
f"The variable(s) {', '.join(unknown)} in '{argument}' are not moderators of Model "
|
|
816
|
+
f"{self.model_num}. Moderators of this model: {', '.join(sorted(moderators)) or 'none'}."
|
|
817
|
+
)
|
|
818
|
+
|
|
782
819
|
def _gen_valid_options(self, arguments):
|
|
783
820
|
"""
|
|
784
821
|
Validate the arguments specified for the different options used in Process.
|
|
@@ -793,8 +830,8 @@ class Process(object):
|
|
|
793
830
|
"The option 'conf' must be an integer between 50 and 100, exclusive.\n"
|
|
794
831
|
)
|
|
795
832
|
|
|
796
|
-
if not isinstance(seed, int) or (
|
|
797
|
-
errstr += "The option 'seed' must be
|
|
833
|
+
if seed is not None and (not isinstance(seed, (int, np.integer)) or not (0 <= seed <= 2**32 - 1)):
|
|
834
|
+
errstr += "The option 'seed' must be None or an integer between 0 and 2**32 - 1.\n"
|
|
798
835
|
|
|
799
836
|
if options["contrast"] not in [True, False]:
|
|
800
837
|
errstr += "The option 'contrast' must be 'True' or 'False'.\n"
|
|
@@ -804,6 +841,12 @@ class Process(object):
|
|
|
804
841
|
errstr += "The option 'jn' must be 'True' or 'False'.\n"
|
|
805
842
|
if options["hc3"] not in [True, False]:
|
|
806
843
|
errstr += "The option 'hc3' must be 'True' or 'False'.\n"
|
|
844
|
+
if options["cov_type"] not in ["standard", "HC0", "HC1", "HC2", "HC3"]:
|
|
845
|
+
errstr += "The option 'cov_type' must be one of 'standard', 'HC0', 'HC1', 'HC2' or 'HC3'.\n"
|
|
846
|
+
elif options["hc3"] is True:
|
|
847
|
+
if options["cov_type"] not in ["standard", "HC3"]:
|
|
848
|
+
errstr += "The options hc3=True and cov_type disagree; use one or the other.\n"
|
|
849
|
+
options["cov_type"] = "HC3" # hc3 is shorthand for cov_type="HC3" (#52)
|
|
807
850
|
if options["center"] not in [True, False]:
|
|
808
851
|
errstr += "The option 'center' must be 'True' or 'False'.\n"
|
|
809
852
|
if options["quantile"] not in [True, False]:
|
|
@@ -996,9 +1039,9 @@ class Process(object):
|
|
|
996
1039
|
"""
|
|
997
1040
|
# Subset the data to the columns used in the model
|
|
998
1041
|
data = self._data[self.varlist].copy()
|
|
999
|
-
n_obs_before =
|
|
1000
|
-
data = data.dropna().reset_index()
|
|
1001
|
-
n_obs_after =
|
|
1042
|
+
n_obs_before = data.shape[0]
|
|
1043
|
+
data = data.dropna().reset_index(drop=True)
|
|
1044
|
+
n_obs_after = data.shape[0] # rows that survived dropna (#44)
|
|
1002
1045
|
n_obs_null = n_obs_before - n_obs_after
|
|
1003
1046
|
|
|
1004
1047
|
# Map each variable name to a unique variable code, and rename the columns in the data.)
|
|
@@ -1224,7 +1267,9 @@ class Process(object):
|
|
|
1224
1267
|
1. If the two moderators are on two different paths (X to M, or M to Y): both CMM and MMM are reported.
|
|
1225
1268
|
2. If the two moderators are on the same path and form a 3-way interaction: both CMM and MMM are reported.
|
|
1226
1269
|
3. If the two moderators are on the same path and do not form a 3-way: the PMM is reported.
|
|
1227
|
-
4. If
|
|
1270
|
+
4. If a moderator is present on both paths (models 58 to 73, 75 and 76): no index is reported, because
|
|
1271
|
+
the indirect effect is not linear in that moderator and the indices assume it is.
|
|
1272
|
+
MM and PMM match PROCESS 2.16. MMM and CMM follow PROCESS 3 (Hayes, 2018), which 2.16 did not report.
|
|
1228
1273
|
|
|
1229
1274
|
This function returns the list of additional analysis to report. If no additional analysis must be performed,
|
|
1230
1275
|
this list is empty.
|
|
@@ -1240,6 +1285,11 @@ class Process(object):
|
|
|
1240
1285
|
if n_mods_ind == 0: # No moderators on indirect path, so no additional analysis.
|
|
1241
1286
|
return []
|
|
1242
1287
|
|
|
1288
|
+
# Rule 4: a moderator on both the X-to-M and the M-to-Y paths makes the indirect effect quadratic in
|
|
1289
|
+
# that moderator, and every index below assumes linearity. PROCESS reports no index then (#43).
|
|
1290
|
+
if self._moderators["x_indirect"] & self._moderators["m"]:
|
|
1291
|
+
return []
|
|
1292
|
+
|
|
1243
1293
|
terms = y_exogvars + m_exogvars
|
|
1244
1294
|
threeway = any(
|
|
1245
1295
|
[1 if len(term.split("*")) == 3 else 0 for term in terms]
|
|
@@ -1269,6 +1319,7 @@ class Process(object):
|
|
|
1269
1319
|
:param path:
|
|
1270
1320
|
:return:
|
|
1271
1321
|
"""
|
|
1322
|
+
self._check_moderator_names(modval, "modval")
|
|
1272
1323
|
modval_symb = {self._var_to_symb[k]: v for k, v in modval.items()}
|
|
1273
1324
|
spotlight_values_symb = self._spotlight_values.copy()
|
|
1274
1325
|
|
|
@@ -1350,13 +1401,19 @@ class Process(object):
|
|
|
1350
1401
|
m_var = self._symb_to_var[m]
|
|
1351
1402
|
if modval_parsed.get(m_var) is None:
|
|
1352
1403
|
warnings.warn(
|
|
1353
|
-
f"The moderator {m_var} exerts an influence on the effect
|
|
1354
|
-
|
|
1355
|
-
|
|
1404
|
+
f"The moderator {m_var} exerts an influence on the effect but is not a factor of the graph; "
|
|
1405
|
+
"its value has been set to 0.",
|
|
1406
|
+
UserWarning,
|
|
1407
|
+
stacklevel=3,
|
|
1356
1408
|
)
|
|
1357
1409
|
modval_parsed[m_var] = [0]
|
|
1358
1410
|
return modval_parsed
|
|
1359
1411
|
|
|
1412
|
+
@property
|
|
1413
|
+
def dv(self):
|
|
1414
|
+
"""The name of the dependent variable (the outcome Y). `iv` holds the same value for compatibility."""
|
|
1415
|
+
return self.iv
|
|
1416
|
+
|
|
1360
1417
|
# API
|
|
1361
1418
|
def summary(self):
|
|
1362
1419
|
"""
|
|
@@ -1816,16 +1873,3 @@ class Process(object):
|
|
|
1816
1873
|
plot_kws,
|
|
1817
1874
|
err_kws,
|
|
1818
1875
|
)
|
|
1819
|
-
|
|
1820
|
-
# DEPRECATED METHODS
|
|
1821
|
-
def plot_indirect_effects(self, *args, **kwargs):
|
|
1822
|
-
raise DeprecationWarning(
|
|
1823
|
-
"The method 'plot_indirect_effects' has been deprecated. Please use the equivalent method named \
|
|
1824
|
-
'plot_conditional_indirect_effects."
|
|
1825
|
-
)
|
|
1826
|
-
|
|
1827
|
-
def plot_direct_effects(self, *args, **kwargs):
|
|
1828
|
-
raise DeprecationWarning(
|
|
1829
|
-
"The method 'plot_direct_effects' has been deprecated. Please use the equivalent method named \
|
|
1830
|
-
'plot_conditional_direct_effects."
|
|
1831
|
-
)
|
|
@@ -4,7 +4,7 @@ import matplotlib.pyplot as plt
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
from numpy import dot
|
|
6
6
|
from numpy.linalg import inv, LinAlgError
|
|
7
|
-
from scipy.stats import norm
|
|
7
|
+
from scipy.stats import norm, t
|
|
8
8
|
from seaborn import FacetGrid
|
|
9
9
|
|
|
10
10
|
|
|
@@ -16,6 +16,15 @@ def z_score(conf):
|
|
|
16
16
|
return norm.ppf((100 - (100 - conf) / 2) / 100)
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def t_score(conf, df):
|
|
20
|
+
"""
|
|
21
|
+
:param conf: Desired level of confidence
|
|
22
|
+
:param df: Degrees of freedom of the t distribution
|
|
23
|
+
:return: The critical t value corresponding to the level of confidence desired.
|
|
24
|
+
"""
|
|
25
|
+
return t.ppf((100 - (100 - conf) / 2) / 100, df)
|
|
26
|
+
|
|
27
|
+
|
|
19
28
|
def bias_corrected_ci(estimate, samples, conf=95):
|
|
20
29
|
"""
|
|
21
30
|
Return the bias-corrected bootstrap confidence interval for an estimate
|
|
@@ -24,8 +33,10 @@ def bias_corrected_ci(estimate, samples, conf=95):
|
|
|
24
33
|
:param conf: Level of the desired confidence interval
|
|
25
34
|
:return: Bias-corrected bootstrapped LLCI and ULCI for the estimate.
|
|
26
35
|
"""
|
|
27
|
-
# noinspection PyUnresolvedReferences
|
|
28
36
|
ptilde = ((samples < estimate) * 1).mean()
|
|
37
|
+
# Every draw on one side of the estimate would make the bias correction infinite; clip to the
|
|
38
|
+
# resolution of the bootstrap distribution instead (#49).
|
|
39
|
+
ptilde = min(max(ptilde, 1 / len(samples)), 1 - 1 / len(samples))
|
|
29
40
|
Z = norm.ppf(ptilde)
|
|
30
41
|
Zci = z_score(conf)
|
|
31
42
|
Zlow, Zhigh = -Zci + 2 * Z, Zci + 2 * Z
|
|
@@ -47,15 +58,16 @@ def percentile_ci(samples, conf):
|
|
|
47
58
|
return np.percentile(samples, [lower, upper])
|
|
48
59
|
|
|
49
60
|
|
|
61
|
+
class ConvergenceError(RuntimeError):
|
|
62
|
+
"""Raised when the Newton-Raphson estimation of a logistic model does not converge."""
|
|
63
|
+
|
|
64
|
+
|
|
50
65
|
def fast_OLS(endog, exog):
|
|
51
66
|
"""
|
|
52
67
|
A simple function for (X'X)^(-1)X'Y
|
|
53
68
|
:return: The Kx1 array of estimated coefficients.
|
|
54
69
|
"""
|
|
55
|
-
|
|
56
|
-
return dot(dot(inv(dot(exog.T, exog)), exog.T), endog).squeeze()
|
|
57
|
-
except LinAlgError:
|
|
58
|
-
raise LinAlgError
|
|
70
|
+
return dot(dot(inv(dot(exog.T, exog)), exog.T), endog).squeeze()
|
|
59
71
|
|
|
60
72
|
|
|
61
73
|
def logit_cdf(X):
|
|
@@ -109,17 +121,22 @@ def fast_optimize(endog, exog, n_obs=0, n_vars=0, max_iter=10000, tolerance=1e-1
|
|
|
109
121
|
"""
|
|
110
122
|
iterations = 0
|
|
111
123
|
oldparams = np.inf
|
|
112
|
-
newparams = np.
|
|
124
|
+
newparams = np.zeros(n_vars)
|
|
113
125
|
while iterations < max_iter and np.any(np.abs(newparams - oldparams) > tolerance):
|
|
114
126
|
oldparams = newparams
|
|
115
127
|
try:
|
|
116
128
|
H = logit_hessian(exog, oldparams, n_obs)
|
|
117
|
-
newparams = oldparams - dot(
|
|
118
|
-
inv(H), logit_score(endog, exog, oldparams, n_obs)
|
|
119
|
-
)
|
|
129
|
+
newparams = oldparams - dot(inv(H), logit_score(endog, exog, oldparams, n_obs))
|
|
120
130
|
except LinAlgError:
|
|
121
|
-
raise
|
|
131
|
+
raise ConvergenceError("The Hessian of the logistic regression is singular.")
|
|
122
132
|
iterations += 1
|
|
133
|
+
if not np.all(np.isfinite(newparams)):
|
|
134
|
+
raise ConvergenceError("The logistic regression diverged (the outcome may be perfectly separated).")
|
|
135
|
+
if np.any(np.abs(newparams - oldparams) > tolerance):
|
|
136
|
+
raise ConvergenceError(
|
|
137
|
+
f"The logistic regression did not converge in {max_iter} iterations "
|
|
138
|
+
"(increase 'iterate', relax 'convergence', or check the outcome for separation)."
|
|
139
|
+
)
|
|
123
140
|
return newparams
|
|
124
141
|
|
|
125
142
|
|
|
@@ -130,8 +147,7 @@ def bootstrap_sampler(n_obs, seed=None):
|
|
|
130
147
|
:param seed: The seed to use for the random number generator
|
|
131
148
|
:return: Bootstrapped indices of size n_obs
|
|
132
149
|
"""
|
|
133
|
-
seeder = np.random.RandomState(seed)
|
|
134
|
-
seeder.seed(seed)
|
|
150
|
+
seeder = np.random.RandomState(seed) # None draws fresh entropy (#45)
|
|
135
151
|
while True:
|
|
136
152
|
yield seeder.randint(n_obs, size=n_obs)
|
|
137
153
|
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
from numpy import ndarray
|
|
2
|
-
from typing import Any, Dict, List, Optional, Tuple, Union, Iterable, Callable
|
|
3
|
-
|
|
4
|
-
from pandas import DataFrame
|
|
5
|
-
|
|
6
|
-
class BaseLogit:
|
|
7
|
-
_endog: ndarray
|
|
8
|
-
_exog: ndarray
|
|
9
|
-
_n_obs: int
|
|
10
|
-
_n_vars: int
|
|
11
|
-
_options: Dict[str, Any]
|
|
12
|
-
def __init__(
|
|
13
|
-
self, endog: ndarray, exog: ndarray, options: Dict[str, Any]
|
|
14
|
-
) -> None: ...
|
|
15
|
-
@staticmethod
|
|
16
|
-
def _cdf(X: ndarray) -> ndarray: ...
|
|
17
|
-
def _hessian(self, params: ndarray) -> ndarray: ...
|
|
18
|
-
def _loglike(self, params: ndarray) -> float: ...
|
|
19
|
-
def _loglikeobs(self, params: ndarray) -> ndarray: ...
|
|
20
|
-
def _optimize(self) -> ndarray: ...
|
|
21
|
-
def _score(self, params: ndarray) -> ndarray: ...
|
|
22
|
-
|
|
23
|
-
class NullLogitModel(BaseLogit):
|
|
24
|
-
def __init__(self, endog: ndarray, options: Optional[Dict[str, Any]]) -> None: ...
|
|
25
|
-
|
|
26
|
-
class BaseOutcomeModel:
|
|
27
|
-
_data: ndarray
|
|
28
|
-
_derivative: ndarray
|
|
29
|
-
_endog: ndarray
|
|
30
|
-
_endogvar: str
|
|
31
|
-
_exog: ndarray
|
|
32
|
-
_exogvars: List[str]
|
|
33
|
-
_n_obs: int
|
|
34
|
-
_n_vars: int
|
|
35
|
-
_options: Dict[Union[None, str], Any]
|
|
36
|
-
_symb_to_ind: Dict[str, int]
|
|
37
|
-
_symb_to_var: Dict[str, str]
|
|
38
|
-
_varnames: List[str]
|
|
39
|
-
estimation_results: Dict[str, Union[ndarray, float, int, List[str]]]
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
data: ndarray,
|
|
43
|
-
endogvar: str,
|
|
44
|
-
exogvars: List[str],
|
|
45
|
-
symb_to_ind: Dict[str, int],
|
|
46
|
-
symb_to_var: Dict[str, str],
|
|
47
|
-
options: Optional[Dict[str, Any]] = ...,
|
|
48
|
-
) -> None: ...
|
|
49
|
-
def _gen_derivative(self, wrt: str) -> ndarray: ...
|
|
50
|
-
def coeff_summary(self) -> DataFrame: ...
|
|
51
|
-
def _estimate(self) -> Dict[str, Union[ndarray, float, int, List[str]]]: ...
|
|
52
|
-
|
|
53
|
-
class ParallelMediationModel:
|
|
54
|
-
_analysis_list: List[str]
|
|
55
|
-
_base_derivs: Dict[str, Union[ndarray, List[ndarray]]]
|
|
56
|
-
_boot_betas_m: ndarray
|
|
57
|
-
_boot_betas_y: ndarray
|
|
58
|
-
_compute_betas_m: Callable[[ndarray, ndarray], ndarray]
|
|
59
|
-
_compute_betas_y: Callable[[ndarray, ndarray], ndarray]
|
|
60
|
-
_data: ndarray
|
|
61
|
-
_endog_vars_m: List[str]
|
|
62
|
-
_exog_inds_m: List[int]
|
|
63
|
-
_exog_inds_y: List[int]
|
|
64
|
-
_exog_terms_m: List[str]
|
|
65
|
-
_exog_terms_y: List[str]
|
|
66
|
-
_has_moderation: bool
|
|
67
|
-
_ind_y: int
|
|
68
|
-
_inds_m: List[int]
|
|
69
|
-
_moderators_symb: List[str]
|
|
70
|
-
_moderators_values: List[List[float]]
|
|
71
|
-
_n_fail_samples: int
|
|
72
|
-
_n_meds: int
|
|
73
|
-
_n_obs: int
|
|
74
|
-
_options: Dict[Union[None, str], Any]
|
|
75
|
-
_symb_to_ind: Dict[str, int]
|
|
76
|
-
_symb_to_var: Dict[str, str]
|
|
77
|
-
_true_betas_m: ndarray
|
|
78
|
-
_true_betas_y: ndarray
|
|
79
|
-
_vars_m: List[str]
|
|
80
|
-
_vars_y: List[str]
|
|
81
|
-
estimation_results: Dict[str, ndarray]
|
|
82
|
-
def __init__(
|
|
83
|
-
self,
|
|
84
|
-
data: ndarray,
|
|
85
|
-
exog_terms_y: List[str],
|
|
86
|
-
exog_terms_m: List[str],
|
|
87
|
-
mod_symb: Iterable[str],
|
|
88
|
-
spot_values: Dict[str, List[float]],
|
|
89
|
-
n_meds: int,
|
|
90
|
-
analysis_list: List[str],
|
|
91
|
-
symb_to_ind: Dict[str, int],
|
|
92
|
-
symb_to_var: Dict[str, str],
|
|
93
|
-
options: Optional[Dict[str, Any]] = ...,
|
|
94
|
-
) -> None: ...
|
|
95
|
-
def _simple_ind_effects(self) -> Dict[str, ndarray]: ...
|
|
96
|
-
def _simple_ind_effects_wrapper(self) -> DataFrame: ...
|
|
97
|
-
def _MM_index(self) -> Dict[str, ndarray]: ...
|
|
98
|
-
def _MMM_index(self) -> Dict[str, ndarray]: ...
|
|
99
|
-
def _CMM_index(self) -> Dict[str, ndarray]: ...
|
|
100
|
-
def _PMM_index(self) -> Dict[str, ndarray]: ...
|
|
101
|
-
def _MM_index_wrapper(self) -> DataFrame: ...
|
|
102
|
-
def _MMM_index_wrapper(self) -> DataFrame: ...
|
|
103
|
-
def _CMM_index_wrapper(self) -> DataFrame: ...
|
|
104
|
-
def _PMM_index_wrapper(self) -> DataFrame: ...
|
|
105
|
-
def MM_index_summary(self) -> DataFrame: ...
|
|
106
|
-
def MMM_index_summary(self) -> DataFrame: ...
|
|
107
|
-
def CMM_index_summary(self) -> DataFrame: ...
|
|
108
|
-
def PMM_index_summary(self) -> DataFrame: ...
|
|
109
|
-
def _cond_ind_effects(self) -> DataFrame: ...
|
|
110
|
-
def _cond_ind_effects_wrapper(self) -> DataFrame: ...
|
|
111
|
-
def _estimate_bootstrapped_params(self) -> Tuple[ndarray, ndarray, int]: ...
|
|
112
|
-
def _estimate_true_params(self) -> Tuple[ndarray, List[ndarray]]: ...
|
|
113
|
-
def _floodlight_analysis(
|
|
114
|
-
self,
|
|
115
|
-
med_index: int,
|
|
116
|
-
mod_symb: str,
|
|
117
|
-
modval_range: List[float],
|
|
118
|
-
other_modval_symb: Dict[str, int],
|
|
119
|
-
atol: float,
|
|
120
|
-
rtol: float,
|
|
121
|
-
) -> Union[List[List[float]]]: ...
|
|
122
|
-
def _gen_derivatives(self) -> Dict[str, Union[ndarray, List[ndarray]]]: ...
|
|
123
|
-
def _get_conditional_indirect_effects(
|
|
124
|
-
self,
|
|
125
|
-
med_index: int,
|
|
126
|
-
mod_symb: Iterable[str],
|
|
127
|
-
mod_values: Union[ndarray, List[Iterable[float]]],
|
|
128
|
-
) -> Tuple[ndarray, ndarray, ndarray, ndarray, ndarray]: ...
|
|
129
|
-
def _indirect_effect_at(
|
|
130
|
-
self, med_index: int, mod_dict: Dict[str, float]
|
|
131
|
-
) -> Tuple[float, ndarray, float, float, float]: ...
|
|
132
|
-
def coeff_summary(self) -> DataFrame: ...
|
|
133
|
-
def summary(self) -> str: ...
|
|
134
|
-
|
|
135
|
-
class LogitOutcomeModel(BaseOutcomeModel, BaseLogit):
|
|
136
|
-
def __init__(
|
|
137
|
-
self,
|
|
138
|
-
data: ndarray,
|
|
139
|
-
endogvar: str,
|
|
140
|
-
exogvars: List[str],
|
|
141
|
-
symb_to_ind: Dict[str, int],
|
|
142
|
-
symb_to_var: Dict[str, str],
|
|
143
|
-
options: Optional[Dict[str, Any]] = ...,
|
|
144
|
-
) -> None: ...
|
|
145
|
-
def _estimate(self) -> Dict[str, Union[ndarray, float, int, List[str]]]: ...
|
|
146
|
-
|
|
147
|
-
class OLSOutcomeModel(BaseOutcomeModel):
|
|
148
|
-
def __init__(
|
|
149
|
-
self,
|
|
150
|
-
data: ndarray,
|
|
151
|
-
endogvar: str,
|
|
152
|
-
exogvars: List[str],
|
|
153
|
-
symb_to_ind: Dict[str, int],
|
|
154
|
-
symb_to_var: Dict[str, str],
|
|
155
|
-
options: Optional[Dict[str, Any]] = ...,
|
|
156
|
-
) -> None: ...
|
|
157
|
-
def _estimate(self) -> Dict[str, Union[ndarray, float, int, List[str]]]: ...
|
|
158
|
-
|
|
159
|
-
class DirectEffectModel:
|
|
160
|
-
_derivative: ndarray
|
|
161
|
-
_estimation_results: Dict[str, ndarray]
|
|
162
|
-
_has_mediation: bool
|
|
163
|
-
_has_moderation: bool
|
|
164
|
-
_is_logit: bool
|
|
165
|
-
_model: Union[LogitOutcomeModel, OLSOutcomeModel]
|
|
166
|
-
_moderators_symb: List[str]
|
|
167
|
-
_moderators_values: List[List[float]]
|
|
168
|
-
_options: Dict[Union[None, str], Any]
|
|
169
|
-
_symb_to_var: Dict[str, str]
|
|
170
|
-
def __init__(
|
|
171
|
-
self,
|
|
172
|
-
model: OLSOutcomeModel,
|
|
173
|
-
mod_symb: Iterable[str],
|
|
174
|
-
spot_values: Dict[str, List[float]],
|
|
175
|
-
has_mediation: bool,
|
|
176
|
-
symb_to_var: Dict[str, str],
|
|
177
|
-
options: Optional[Dict[str, Any]] = ...,
|
|
178
|
-
) -> None: ...
|
|
179
|
-
def _direct_effect_at(
|
|
180
|
-
self, mod_dict: Dict[str, float]
|
|
181
|
-
) -> Tuple[float, float, float, float]: ...
|
|
182
|
-
def _estimate(self) -> Dict[str, ndarray]: ...
|
|
183
|
-
def _floodlight_analysis(
|
|
184
|
-
self,
|
|
185
|
-
mod_symb: str,
|
|
186
|
-
modval_range: List[float],
|
|
187
|
-
other_modval_symb: Dict[str, int],
|
|
188
|
-
atol: float,
|
|
189
|
-
rtol: float,
|
|
190
|
-
) -> List[List[float]]: ...
|
|
191
|
-
def _get_conditional_direct_effects(
|
|
192
|
-
self, mod_symb: List[str], mod_values: Union[ndarray, List[Iterable[float]]]
|
|
193
|
-
) -> Tuple[ndarray, ndarray, ndarray, ndarray]: ...
|
|
194
|
-
|
|
195
|
-
class BaseFloodlightAnalysis:
|
|
196
|
-
sig_regions: List[List[float]]
|
|
197
|
-
def __init__(
|
|
198
|
-
self,
|
|
199
|
-
med_name: Optional[str],
|
|
200
|
-
mod_name: str,
|
|
201
|
-
sig_regions: List[List[float]],
|
|
202
|
-
modval_range: List[float],
|
|
203
|
-
other_modval_name: Dict[str, float],
|
|
204
|
-
precision: int,
|
|
205
|
-
) -> None: ...
|
|
206
|
-
def get_significance_regions(self) -> Dict[str, List[float]]: ...
|
|
207
|
-
|
|
208
|
-
class DirectFloodlightAnalysis(BaseFloodlightAnalysis):
|
|
209
|
-
def __init__(
|
|
210
|
-
self,
|
|
211
|
-
mod_name: str,
|
|
212
|
-
sig_regions: List[List[float]],
|
|
213
|
-
modval_range: List[float],
|
|
214
|
-
other_modval_name: Dict[str, int],
|
|
215
|
-
precision: int,
|
|
216
|
-
) -> None: ...
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
class IndirectFloodlightAnalysis(BaseFloodlightAnalysis):
|
|
220
|
-
def __init__(
|
|
221
|
-
self,
|
|
222
|
-
med_name: str,
|
|
223
|
-
mod_name: str,
|
|
224
|
-
sig_regions: List[List[float]],
|
|
225
|
-
modval_range: List[float],
|
|
226
|
-
other_modval_name: Dict[str, int],
|
|
227
|
-
precision: int,
|
|
228
|
-
) -> None: ...
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from typing import Union, Iterable, Dict, List, Any, Set, Tuple, Optional, NoReturn
|
|
3
|
-
|
|
4
|
-
from numpy import ndarray
|
|
5
|
-
from pandas.core.frame import DataFrame
|
|
6
|
-
from seaborn.axisgrid import FacetGrid
|
|
7
|
-
|
|
8
|
-
from .models import (
|
|
9
|
-
OLSOutcomeModel,
|
|
10
|
-
DirectEffectModel,
|
|
11
|
-
ParallelMediationModel,
|
|
12
|
-
LogitOutcomeModel,
|
|
13
|
-
DirectFloodlightAnalysis,
|
|
14
|
-
IndirectFloodlightAnalysis,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
class Process(object):
|
|
18
|
-
__var_kws__: Set[str]
|
|
19
|
-
|
|
20
|
-
__options_kws__: Set[str]
|
|
21
|
-
|
|
22
|
-
__models_vars__: Dict[str, Set[str]]
|
|
23
|
-
|
|
24
|
-
__models_eqs__: Dict[str, Dict[List[str]]]
|
|
25
|
-
|
|
26
|
-
model_num: int
|
|
27
|
-
controls: Iterable
|
|
28
|
-
options = Dict[str, Any]
|
|
29
|
-
varlist = List[str]
|
|
30
|
-
mediators = List[str]
|
|
31
|
-
|
|
32
|
-
iv: str
|
|
33
|
-
n_obs: int
|
|
34
|
-
n_obs_null: int
|
|
35
|
-
n_meds: int
|
|
36
|
-
has_mediation: bool
|
|
37
|
-
outcome_models: Dict[str, Union[OLSOutcomeModel, LogitOutcomeModel]]
|
|
38
|
-
direct_model: DirectEffectModel
|
|
39
|
-
indirect_model: Union[None, ParallelMediationModel]
|
|
40
|
-
centered_vars: Union[List, None]
|
|
41
|
-
|
|
42
|
-
_data: DataFrame
|
|
43
|
-
_moderators: Dict[str, Set[str]]
|
|
44
|
-
_spotlight_values: Dict[str, List[float]]
|
|
45
|
-
_var_to_symb: Dict[str, str]
|
|
46
|
-
_symb_to_var: Dict[str, str]
|
|
47
|
-
_symb_to_ind: Dict[str, int]
|
|
48
|
-
|
|
49
|
-
_equations: List[Tuple[Union[str, List[str]]]]
|
|
50
|
-
def __init__(
|
|
51
|
-
self,
|
|
52
|
-
data: DataFrame,
|
|
53
|
-
model: int,
|
|
54
|
-
modval: Optional[Dict[str, List[float]]],
|
|
55
|
-
cluster: Optional[str],
|
|
56
|
-
boot: Optional[int],
|
|
57
|
-
seed: Optional[int],
|
|
58
|
-
mc: Optional[bool],
|
|
59
|
-
conf: Optional[int],
|
|
60
|
-
effsize: Optional[bool],
|
|
61
|
-
jn: Optional[bool],
|
|
62
|
-
hc3: Optional[bool],
|
|
63
|
-
controls: Optional[Iterable[str]],
|
|
64
|
-
controls_in: str,
|
|
65
|
-
total: Optional[bool],
|
|
66
|
-
contrast: Optional[bool],
|
|
67
|
-
center: Optional[bool],
|
|
68
|
-
quantile: Optional[bool],
|
|
69
|
-
detail: Optional[bool],
|
|
70
|
-
percent: Optional[bool],
|
|
71
|
-
logit: Optional[bool],
|
|
72
|
-
iterate: Optional[int],
|
|
73
|
-
convergence: Optional[float],
|
|
74
|
-
precision: Optional[int],
|
|
75
|
-
suppr_init: Optional[bool],
|
|
76
|
-
**kwargs
|
|
77
|
-
) -> None: ...
|
|
78
|
-
# PRIVATE METHODS
|
|
79
|
-
def _gen_valid_options(self, argument: Dict[str, Any]) -> Dict[str, Any]: ...
|
|
80
|
-
def _gen_valid_varlist(
|
|
81
|
-
self, var_kwargs: Dict[str, Union[str, List]]
|
|
82
|
-
) -> List[str]: ...
|
|
83
|
-
def _gen_analysis_list(self) -> List[str]: ...
|
|
84
|
-
def _gen_spotlight_values(
|
|
85
|
-
self, modval: Optional[Dict[str, List[float]]]
|
|
86
|
-
) -> Dict[str, Iterable[float]]: ...
|
|
87
|
-
def _gen_var_mapping(
|
|
88
|
-
self, var_kwargs: Dict[str, str]
|
|
89
|
-
) -> Tuple[Dict[str, str], Dict[str, str]]: ...
|
|
90
|
-
def _prepare_data(self) -> Tuple[DataFrame, int, int, List[str]]: ...
|
|
91
|
-
def _gen_equations(
|
|
92
|
-
self, all_to_y: List[str], x_to_m: List[str], controls_in: str
|
|
93
|
-
) -> List[Tuple[str, List[str]]]: ...
|
|
94
|
-
def _gen_outcome_models(
|
|
95
|
-
self
|
|
96
|
-
) -> Dict[str, Union[OLSOutcomeModel, LogitOutcomeModel]]: ...
|
|
97
|
-
def _gen_direct_effect_model(self) -> DirectEffectModel: ...
|
|
98
|
-
def _gen_indirect_effect_model(self) -> ParallelMediationModel: ...
|
|
99
|
-
def _print_init(self) -> None: ...
|
|
100
|
-
def _parse_moderator_values(
|
|
101
|
-
self,
|
|
102
|
-
x: str,
|
|
103
|
-
hue: Optional[Union[str, List[str]]],
|
|
104
|
-
row: Optional[str],
|
|
105
|
-
col: Optional[str],
|
|
106
|
-
modval: Optional[Dict[str, Union[ndarray, List[float]]]],
|
|
107
|
-
path: str,
|
|
108
|
-
) -> Dict[str, Union[ndarray, List[float]]]: ...
|
|
109
|
-
# API METHODS
|
|
110
|
-
def summary(self) -> None: ...
|
|
111
|
-
def get_bootstrap_estimates(self) -> DataFrame: ...
|
|
112
|
-
def floodlight_indirect_effect(
|
|
113
|
-
self,
|
|
114
|
-
med_name: str,
|
|
115
|
-
mod_name: str,
|
|
116
|
-
other_modval: Optional[Dict[str, float]],
|
|
117
|
-
atol: Optional[float],
|
|
118
|
-
rtol: Optional[float],
|
|
119
|
-
) -> IndirectFloodlightAnalysis: ...
|
|
120
|
-
def floodlight_direct_effect(
|
|
121
|
-
self,
|
|
122
|
-
mod_name: str,
|
|
123
|
-
other_modval: Optional[Dict[str, float]],
|
|
124
|
-
atol: Optional[float],
|
|
125
|
-
rtol: Optional[float],
|
|
126
|
-
) -> DirectFloodlightAnalysis: ...
|
|
127
|
-
def spotlight_indirect_effect(
|
|
128
|
-
self, med_name: str, spotval: Optional[Dict[str, Union[ndarray, List[float]]]]
|
|
129
|
-
) -> DataFrame: ...
|
|
130
|
-
def spotlight_direct_effect(
|
|
131
|
-
self, spotval: Optional[Dict[str, Union[ndarray, List[float]]]]
|
|
132
|
-
) -> DataFrame: ...
|
|
133
|
-
def plot_conditional_direct_effects(
|
|
134
|
-
self,
|
|
135
|
-
x: str,
|
|
136
|
-
hue: Optional[Union[str, List[str]]],
|
|
137
|
-
row: Optional[str],
|
|
138
|
-
col: Optional[str],
|
|
139
|
-
modval: Optional[Dict[str, Union[ndarray, List[float]]]],
|
|
140
|
-
errstyle: Optional[str],
|
|
141
|
-
hue_format: Optional[str],
|
|
142
|
-
facet_kws: Optional[Dict[str, Any]],
|
|
143
|
-
plot_kws: Optional[Dict[str, Any]],
|
|
144
|
-
err_kws: Optional[Dict[str, Any]],
|
|
145
|
-
) -> FacetGrid: ...
|
|
146
|
-
def plot_conditional_indirect_effects(
|
|
147
|
-
self,
|
|
148
|
-
med_name: str,
|
|
149
|
-
x: str,
|
|
150
|
-
hue: Optional[Union[str, List[str]]],
|
|
151
|
-
row: Optional[str],
|
|
152
|
-
col: Optional[str],
|
|
153
|
-
modval: Optional[Dict[str, Union[ndarray, List[float]]]],
|
|
154
|
-
errstyle: Optional[str],
|
|
155
|
-
hue_format: Optional[str],
|
|
156
|
-
facet_kws: Optional[Dict[str, Any]],
|
|
157
|
-
plot_kws: Optional[Dict[str, Any]],
|
|
158
|
-
err_kws: Optional[Dict[str, Any]],
|
|
159
|
-
) -> FacetGrid: ...
|
|
160
|
-
|
|
161
|
-
# DEPRECATED METHODS
|
|
162
|
-
def plot_indirect_effects(self, *args, **kwargs) -> NoReturn: ...
|
|
163
|
-
def plot_direct_effects(self, *args, **kwargs) -> NoReturn: ...
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
from typing import Callable, Union, Iterable, Dict, List, Optional, Any, Set
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from pandas import DataFrame
|
|
5
|
-
from seaborn import FacetGrid
|
|
6
|
-
|
|
7
|
-
def z_score(conf: float) -> float: ...
|
|
8
|
-
def bias_corrected_ci(
|
|
9
|
-
estimate: np.array, samples: np.array, conf: Union[float, int]
|
|
10
|
-
) -> (float, float): ...
|
|
11
|
-
def percentile_ci(samples: np.array, conf: Union[float, int]) -> np.array: ...
|
|
12
|
-
def fast_OLS(endog: np.array, exog: np.array) -> np.array: ...
|
|
13
|
-
def logit_cdf(X: np.array) -> np.array: ...
|
|
14
|
-
def logit_score(
|
|
15
|
-
endog: np.array, exog: np.array, params: np.array, n_obs: int
|
|
16
|
-
) -> np.array: ...
|
|
17
|
-
def logit_hessian(exog: np.array, params: np.array, n_obs: int) -> np.array: ...
|
|
18
|
-
def fast_optimize(
|
|
19
|
-
endog: np.array,
|
|
20
|
-
exog: np.array,
|
|
21
|
-
n_obs: int,
|
|
22
|
-
n_vars: int,
|
|
23
|
-
max_iter: int,
|
|
24
|
-
tolerance: float = 1e-10,
|
|
25
|
-
) -> np.array: ...
|
|
26
|
-
def bootstrap_sampler(n_obs: int, seed: int) -> np.array: ...
|
|
27
|
-
def eigvals(exog: np.array) -> np.array: ...
|
|
28
|
-
def eval_expression(expr: np.array, values: Dict) -> np.array: ...
|
|
29
|
-
def gen_moderators(
|
|
30
|
-
raw_equations: Dict[str, List[str]], raw_varlist: List[str]
|
|
31
|
-
) -> Dict[str, Set[str]]: ...
|
|
32
|
-
def plot_errorbars(
|
|
33
|
-
x: np.array,
|
|
34
|
-
y: np.array,
|
|
35
|
-
yerrlow: np.array,
|
|
36
|
-
yerrhigh: np.array,
|
|
37
|
-
plot_kws: Optional[Dict[str, Any]],
|
|
38
|
-
err_kws: Optional[Dict[str, Any]],
|
|
39
|
-
*args,
|
|
40
|
-
**kwargs
|
|
41
|
-
) -> None: ...
|
|
42
|
-
def plot_errorbands(
|
|
43
|
-
x: np.array,
|
|
44
|
-
y: np.array,
|
|
45
|
-
llci: np.array,
|
|
46
|
-
ulci: np.array,
|
|
47
|
-
plot_kws: Optional[Dict[str, Any]],
|
|
48
|
-
err_kws: Optional[Dict[str, Any]],
|
|
49
|
-
*args,
|
|
50
|
-
**kwargs
|
|
51
|
-
) -> None: ...
|
|
52
|
-
def plot_conditional_effects(
|
|
53
|
-
df_effects: DataFrame,
|
|
54
|
-
x: str,
|
|
55
|
-
hue: Optional[Union[str, List[str]]],
|
|
56
|
-
row: Optional[str],
|
|
57
|
-
col: Optional[str],
|
|
58
|
-
errstyle: Optional[str],
|
|
59
|
-
hue_format: Optional[str],
|
|
60
|
-
facet_kws: Optional[Dict[str, Any]],
|
|
61
|
-
plot_kws: Optional[Dict[str, Any]],
|
|
62
|
-
err_kws: Optional[Dict[str, Any]],
|
|
63
|
-
) -> FacetGrid: ...
|
|
64
|
-
def find_significance_region(
|
|
65
|
-
spotlight_func: Callable[[Dict], Iterable],
|
|
66
|
-
mod_symb: str,
|
|
67
|
-
modval_min: float,
|
|
68
|
-
modval_max: float,
|
|
69
|
-
modval_other_symb: Dict,
|
|
70
|
-
atol: float,
|
|
71
|
-
rtol: float,
|
|
72
|
-
) -> List[List[float]]: ...
|
|
73
|
-
def search_mid_range(
|
|
74
|
-
spotlight_func: Callable[[Dict], Iterable],
|
|
75
|
-
min_val: float,
|
|
76
|
-
max_val: float,
|
|
77
|
-
mod_symb: str,
|
|
78
|
-
mod_dict: Dict,
|
|
79
|
-
atol: float,
|
|
80
|
-
rtol: float,
|
|
81
|
-
) -> List[List[float]]: ...
|
|
82
|
-
def search_critical_values(
|
|
83
|
-
spotlight_func: Callable[[Dict], Iterable],
|
|
84
|
-
min_val: float,
|
|
85
|
-
max_val: float,
|
|
86
|
-
mod_symb: str,
|
|
87
|
-
mod_dict: Dict,
|
|
88
|
-
slope: str,
|
|
89
|
-
region: str,
|
|
90
|
-
atol: float,
|
|
91
|
-
rtol: float,
|
|
92
|
-
) -> float: ...
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|