PyMetaAnalysis 0.2.0__tar.gz → 0.3.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.
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/CHANGELOG.md +29 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/CITATION.cff +2 -2
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/PKG-INFO +46 -19
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/README.md +45 -18
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/benchmarks/README.md +5 -4
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/benchmarks/benchmark_core.py +14 -2
- pymetaanalysis-0.3.0/docs/guides/meta-regression.md +220 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/plotting.md +32 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/provenance-reporting.md +1 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/index.md +8 -5
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/limitations.md +14 -5
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/methods/statistical-methods.md +121 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/reference/api.md +63 -3
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/reference/report-schema.md +35 -4
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/reference/results.md +69 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/releasing.md +18 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/validation.md +20 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/examples/README.md +4 -1
- pymetaanalysis-0.3.0/examples/meta_regression.ipynb +290 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/mkdocs.yml +1 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/__init__.py +17 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/_version.py +1 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/config.py +18 -0
- pymetaanalysis-0.3.0/src/meta_analyze/design_matrix.py +477 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/estimators/__init__.py +12 -0
- pymetaanalysis-0.3.0/src/meta_analyze/estimators/meta_regression.py +462 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/plotting/__init__.py +2 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/plotting/_utils.py +2 -2
- pymetaanalysis-0.3.0/src/meta_analyze/plotting/regression.py +128 -0
- pymetaanalysis-0.3.0/src/meta_analyze/regression_api.py +396 -0
- pymetaanalysis-0.3.0/src/meta_analyze/regression_results.py +388 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/reporting.py +169 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/README.md +11 -0
- pymetaanalysis-0.3.0/tests/reference/generate_meta_regression_metafor.R +339 -0
- pymetaanalysis-0.3.0/tests/reference/meta_regression_boundary_input.csv +9 -0
- pymetaanalysis-0.3.0/tests/reference/meta_regression_input.csv +16 -0
- pymetaanalysis-0.3.0/tests/reference/meta_regression_metafor.json +1600 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_documentation.py +10 -0
- pymetaanalysis-0.3.0/tests/test_meta_regression.py +634 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_numerical_stability.py +85 -0
- pymetaanalysis-0.3.0/tests/test_properties.py +252 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_r_references.py +331 -1
- pymetaanalysis-0.3.0/tests/test_regression_plotting.py +200 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_release_readiness.py +23 -17
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_reporting.py +1 -1
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tools/inspect_distribution.py +1 -0
- pymetaanalysis-0.2.0/tests/test_properties.py +0 -116
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/.github/workflows/ci.yml +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/.github/workflows/pages.yml +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/.github/workflows/release.yml +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/.gitignore +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/CONTRIBUTING.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/LICENSE +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/SECURITY.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/adr/0001-optional-matplotlib.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/adr/0002-statistical-policy.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/citation.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/development.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/getting-started.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/binary-outcomes.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/continuous-outcomes.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/generic-effects.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/input-data.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/method-selection.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/r-interoperability.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/sensitivity-analysis.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/guides/zero-events.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/installation.md +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/docs/stylesheets/extra.css +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/examples/quickstart.ipynb +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/pyproject.toml +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/api.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/binary_api.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/continuous_api.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/data.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/effect_sizes/__init__.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/effect_sizes/binary.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/effect_sizes/continuous.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/estimators/inverse_variance.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/estimators/mantel_haenszel.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/estimators/tau2.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/exceptions.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/heterogeneity.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/plotting/forest.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/plotting/funnel.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/plotting/subgroup_forest.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/provenance.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/py.typed +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/results.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/sensitivity.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/src/meta_analyze/subgroups.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/binary_input.csv +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/binary_metafor.json +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/binary_sparse_input.csv +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/continuous_input.csv +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/continuous_metafor.json +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generate_binary_metafor.R +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generate_continuous_metafor.R +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generate_generic_metafor.R +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generate_workflow_metafor.R +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generic_input.csv +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/generic_metafor.json +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/workflow_input.csv +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/reference/workflow_metafor.json +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_api.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_binary.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_continuous.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_estimators.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_funnel_plot.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_plotting.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_reference_results.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_sensitivity.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tests/test_subgroups.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tools/check_release.py +0 -0
- {pymetaanalysis-0.2.0 → pymetaanalysis-0.3.0}/tools/execute_notebooks.py +0 -0
|
@@ -6,6 +6,35 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.3.0 - 2026-07-22
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- pandas-first `meta_regression()` for numeric, explicitly encoded categorical,
|
|
14
|
+
and multiple study-level moderators;
|
|
15
|
+
- common- and mixed-effects weighted regression with generalized DL, PM, and
|
|
16
|
+
REML residual tau-squared estimators;
|
|
17
|
+
- normal, Hartung-Knapp, and safeguarded Hartung-Knapp coefficient inference,
|
|
18
|
+
distribution-explicit moderator tests, residual heterogeneity, pseudo-R²,
|
|
19
|
+
prediction, provenance, and structured reports;
|
|
20
|
+
- optional weighted bubble plots for intercept-containing Meta-regression fits
|
|
21
|
+
with exactly one numeric moderator;
|
|
22
|
+
- independent R `metafor` fixtures covering numeric, categorical,
|
|
23
|
+
multivariable, zero-tau-squared, missing-row, and small-sample cases;
|
|
24
|
+
- an executable Meta-regression notebook plus a multivariable performance
|
|
25
|
+
baseline and expanded property, numerical-stability, and warning tests.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- report schema 1.2 adds the `meta_regression` report type.
|
|
30
|
+
|
|
31
|
+
## 0.2.1 - 2026-07-17
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- README documentation and repository links use absolute URLs so they resolve
|
|
36
|
+
correctly when the project description is rendered on PyPI.
|
|
37
|
+
|
|
9
38
|
## 0.2.0 - 2026-07-16
|
|
10
39
|
|
|
11
40
|
### Added
|
|
@@ -8,8 +8,8 @@ authors:
|
|
|
8
8
|
- family-names: Ding
|
|
9
9
|
given-names: Zhaobo
|
|
10
10
|
email: ding.zb@yahoo.com
|
|
11
|
-
version: 0.
|
|
12
|
-
date-released: 2026-07-
|
|
11
|
+
version: 0.3.0
|
|
12
|
+
date-released: 2026-07-22
|
|
13
13
|
repository-code: https://github.com/ZhaoboDing/PyMetaAnalysis
|
|
14
14
|
url: https://zhaoboding.github.io/PyMetaAnalysis/
|
|
15
15
|
license: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyMetaAnalysis
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A pandas-first, auditable meta-analysis library for Python
|
|
5
5
|
Project-URL: Documentation, https://zhaoboding.github.io/PyMetaAnalysis/
|
|
6
6
|
Project-URL: Source, https://github.com/ZhaoboDing/PyMetaAnalysis
|
|
@@ -51,7 +51,7 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
|
|
52
52
|
[](https://github.com/ZhaoboDing/PyMetaAnalysis/actions/workflows/ci.yml)
|
|
53
53
|
[](https://zhaoboding.github.io/PyMetaAnalysis/)
|
|
54
|
-
[](LICENSE)
|
|
54
|
+
[](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/LICENSE)
|
|
55
55
|
|
|
56
56
|
PyMetaAnalysis is an early-stage, pandas-first Python library for conventional
|
|
57
57
|
study-level meta-analysis. It accepts DataFrames, NumPy arrays, and ordinary
|
|
@@ -111,6 +111,22 @@ Omit `study=` to use the DataFrame index. Supplying `subgroup=` returns a
|
|
|
111
111
|
dedicated result containing group fits, the overall fit, and a formal test for
|
|
112
112
|
subgroup differences.
|
|
113
113
|
|
|
114
|
+
Study-level moderators use the dedicated Meta-regression entry point:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
regression = ma.meta_regression(
|
|
118
|
+
studies,
|
|
119
|
+
effect="effect",
|
|
120
|
+
standard_error="se",
|
|
121
|
+
moderators=["mean_age", "region"],
|
|
122
|
+
categorical={"region": ["Europe", "Asia", "North America"]},
|
|
123
|
+
)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Categorical levels are explicit and ordered; the first value is the treatment-
|
|
127
|
+
coding reference. Moderator coefficients describe study-level associations,
|
|
128
|
+
not individual-level or causal effects.
|
|
129
|
+
|
|
114
130
|
## Supported analyses
|
|
115
131
|
|
|
116
132
|
| Input | Effects | Pooling/models |
|
|
@@ -118,6 +134,7 @@ subgroup differences.
|
|
|
118
134
|
| Effect + sampling variance or standard error | Generic | Common/random inverse variance |
|
|
119
135
|
| Two-group events + totals | OR, RR, RD | Common MH OR/RR; common/random IV |
|
|
120
136
|
| Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
|
|
137
|
+
| Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
|
|
121
138
|
|
|
122
139
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
123
140
|
and DerSimonian-Laird tau-squared estimators. Mean confidence intervals support
|
|
@@ -172,24 +189,28 @@ ax = result.funnel()
|
|
|
172
189
|
|
|
173
190
|
Plotting methods return Matplotlib axes and never call `show()`. Funnel plots
|
|
174
191
|
are descriptive small-study-effect diagnostics, not proof of publication bias.
|
|
192
|
+
An eligible single-numeric-moderator Meta-regression result additionally
|
|
193
|
+
provides `regression.bubble()` with fitted confidence and optional prediction
|
|
194
|
+
bands.
|
|
175
195
|
|
|
176
196
|
## Documentation
|
|
177
197
|
|
|
178
198
|
The complete documentation is published at
|
|
179
199
|
[zhaoboding.github.io/PyMetaAnalysis](https://zhaoboding.github.io/PyMetaAnalysis/).
|
|
180
200
|
|
|
181
|
-
- [Installation](
|
|
182
|
-
- [Getting started](
|
|
183
|
-
- [Input data and row decisions](
|
|
184
|
-
- [Generic](
|
|
185
|
-
- [
|
|
186
|
-
- [
|
|
187
|
-
- [
|
|
188
|
-
- [
|
|
189
|
-
- [
|
|
190
|
-
- [
|
|
191
|
-
|
|
192
|
-
|
|
201
|
+
- [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
|
|
202
|
+
- [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
|
|
203
|
+
- [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
|
|
204
|
+
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), and [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/) guides
|
|
205
|
+
- [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
|
|
206
|
+
- [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
|
|
207
|
+
- [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
|
|
208
|
+
- [Public API](https://zhaoboding.github.io/PyMetaAnalysis/reference/api/), [result objects](https://zhaoboding.github.io/PyMetaAnalysis/reference/results/), and [report schema](https://zhaoboding.github.io/PyMetaAnalysis/reference/report-schema/)
|
|
209
|
+
- [Validation strategy](https://zhaoboding.github.io/PyMetaAnalysis/validation/) and [scope/limitations](https://zhaoboding.github.io/PyMetaAnalysis/limitations/)
|
|
210
|
+
- [Citation guidance](https://zhaoboding.github.io/PyMetaAnalysis/citation/)
|
|
211
|
+
- [R `meta`/`metafor` mapping](https://zhaoboding.github.io/PyMetaAnalysis/guides/r-interoperability/)
|
|
212
|
+
|
|
213
|
+
An executable [end-to-end notebook](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/examples/quickstart.ipynb) uses synthetic
|
|
193
214
|
data to demonstrate analysis, provenance, reporting, sensitivity, and plotting.
|
|
194
215
|
|
|
195
216
|
Build the complete site locally with:
|
|
@@ -207,16 +228,22 @@ edge cases, and committed R `metafor` reference fixtures. CI covers Python
|
|
|
207
228
|
distribution builds.
|
|
208
229
|
|
|
209
230
|
This is independent cross-software validation, not a formal external
|
|
210
|
-
statistical audit. See
|
|
231
|
+
statistical audit. See
|
|
232
|
+
[validation](https://zhaoboding.github.io/PyMetaAnalysis/validation/) for exact
|
|
233
|
+
coverage.
|
|
211
234
|
|
|
212
235
|
## Contributing
|
|
213
236
|
|
|
214
|
-
See
|
|
215
|
-
[
|
|
237
|
+
See
|
|
238
|
+
[CONTRIBUTING.md](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/CONTRIBUTING.md)
|
|
239
|
+
and the full
|
|
240
|
+
[development guide](https://zhaoboding.github.io/PyMetaAnalysis/development/).
|
|
241
|
+
Statistical changes require formula
|
|
216
242
|
documentation, boundary tests, and an independent comparison where available.
|
|
217
243
|
|
|
218
|
-
Security-sensitive reports should follow
|
|
244
|
+
Security-sensitive reports should follow
|
|
245
|
+
[SECURITY.md](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/SECURITY.md).
|
|
219
246
|
|
|
220
247
|
## License
|
|
221
248
|
|
|
222
|
-
[MIT](LICENSE)
|
|
249
|
+
[MIT](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/LICENSE)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ZhaoboDing/PyMetaAnalysis/actions/workflows/ci.yml)
|
|
4
4
|
[](https://zhaoboding.github.io/PyMetaAnalysis/)
|
|
5
|
-
[](LICENSE)
|
|
5
|
+
[](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/LICENSE)
|
|
6
6
|
|
|
7
7
|
PyMetaAnalysis is an early-stage, pandas-first Python library for conventional
|
|
8
8
|
study-level meta-analysis. It accepts DataFrames, NumPy arrays, and ordinary
|
|
@@ -62,6 +62,22 @@ Omit `study=` to use the DataFrame index. Supplying `subgroup=` returns a
|
|
|
62
62
|
dedicated result containing group fits, the overall fit, and a formal test for
|
|
63
63
|
subgroup differences.
|
|
64
64
|
|
|
65
|
+
Study-level moderators use the dedicated Meta-regression entry point:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
regression = ma.meta_regression(
|
|
69
|
+
studies,
|
|
70
|
+
effect="effect",
|
|
71
|
+
standard_error="se",
|
|
72
|
+
moderators=["mean_age", "region"],
|
|
73
|
+
categorical={"region": ["Europe", "Asia", "North America"]},
|
|
74
|
+
)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Categorical levels are explicit and ordered; the first value is the treatment-
|
|
78
|
+
coding reference. Moderator coefficients describe study-level associations,
|
|
79
|
+
not individual-level or causal effects.
|
|
80
|
+
|
|
65
81
|
## Supported analyses
|
|
66
82
|
|
|
67
83
|
| Input | Effects | Pooling/models |
|
|
@@ -69,6 +85,7 @@ subgroup differences.
|
|
|
69
85
|
| Effect + sampling variance or standard error | Generic | Common/random inverse variance |
|
|
70
86
|
| Two-group events + totals | OR, RR, RD | Common MH OR/RR; common/random IV |
|
|
71
87
|
| Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
|
|
88
|
+
| Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
|
|
72
89
|
|
|
73
90
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
74
91
|
and DerSimonian-Laird tau-squared estimators. Mean confidence intervals support
|
|
@@ -123,24 +140,28 @@ ax = result.funnel()
|
|
|
123
140
|
|
|
124
141
|
Plotting methods return Matplotlib axes and never call `show()`. Funnel plots
|
|
125
142
|
are descriptive small-study-effect diagnostics, not proof of publication bias.
|
|
143
|
+
An eligible single-numeric-moderator Meta-regression result additionally
|
|
144
|
+
provides `regression.bubble()` with fitted confidence and optional prediction
|
|
145
|
+
bands.
|
|
126
146
|
|
|
127
147
|
## Documentation
|
|
128
148
|
|
|
129
149
|
The complete documentation is published at
|
|
130
150
|
[zhaoboding.github.io/PyMetaAnalysis](https://zhaoboding.github.io/PyMetaAnalysis/).
|
|
131
151
|
|
|
132
|
-
- [Installation](
|
|
133
|
-
- [Getting started](
|
|
134
|
-
- [Input data and row decisions](
|
|
135
|
-
- [Generic](
|
|
136
|
-
- [
|
|
137
|
-
- [
|
|
138
|
-
- [
|
|
139
|
-
- [
|
|
140
|
-
- [
|
|
141
|
-
- [
|
|
142
|
-
|
|
143
|
-
|
|
152
|
+
- [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
|
|
153
|
+
- [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
|
|
154
|
+
- [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
|
|
155
|
+
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), and [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/) guides
|
|
156
|
+
- [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
|
|
157
|
+
- [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
|
|
158
|
+
- [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
|
|
159
|
+
- [Public API](https://zhaoboding.github.io/PyMetaAnalysis/reference/api/), [result objects](https://zhaoboding.github.io/PyMetaAnalysis/reference/results/), and [report schema](https://zhaoboding.github.io/PyMetaAnalysis/reference/report-schema/)
|
|
160
|
+
- [Validation strategy](https://zhaoboding.github.io/PyMetaAnalysis/validation/) and [scope/limitations](https://zhaoboding.github.io/PyMetaAnalysis/limitations/)
|
|
161
|
+
- [Citation guidance](https://zhaoboding.github.io/PyMetaAnalysis/citation/)
|
|
162
|
+
- [R `meta`/`metafor` mapping](https://zhaoboding.github.io/PyMetaAnalysis/guides/r-interoperability/)
|
|
163
|
+
|
|
164
|
+
An executable [end-to-end notebook](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/examples/quickstart.ipynb) uses synthetic
|
|
144
165
|
data to demonstrate analysis, provenance, reporting, sensitivity, and plotting.
|
|
145
166
|
|
|
146
167
|
Build the complete site locally with:
|
|
@@ -158,16 +179,22 @@ edge cases, and committed R `metafor` reference fixtures. CI covers Python
|
|
|
158
179
|
distribution builds.
|
|
159
180
|
|
|
160
181
|
This is independent cross-software validation, not a formal external
|
|
161
|
-
statistical audit. See
|
|
182
|
+
statistical audit. See
|
|
183
|
+
[validation](https://zhaoboding.github.io/PyMetaAnalysis/validation/) for exact
|
|
184
|
+
coverage.
|
|
162
185
|
|
|
163
186
|
## Contributing
|
|
164
187
|
|
|
165
|
-
See
|
|
166
|
-
[
|
|
188
|
+
See
|
|
189
|
+
[CONTRIBUTING.md](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/CONTRIBUTING.md)
|
|
190
|
+
and the full
|
|
191
|
+
[development guide](https://zhaoboding.github.io/PyMetaAnalysis/development/).
|
|
192
|
+
Statistical changes require formula
|
|
167
193
|
documentation, boundary tests, and an independent comparison where available.
|
|
168
194
|
|
|
169
|
-
Security-sensitive reports should follow
|
|
195
|
+
Security-sensitive reports should follow
|
|
196
|
+
[SECURITY.md](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/SECURITY.md).
|
|
170
197
|
|
|
171
198
|
## License
|
|
172
199
|
|
|
173
|
-
[MIT](LICENSE)
|
|
200
|
+
[MIT](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/LICENSE)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Core performance baseline
|
|
2
2
|
|
|
3
|
-
`benchmark_core.py` measures representative generic, binary, and
|
|
4
|
-
random-effects fits using deterministic synthetic
|
|
5
|
-
primary performance requirement; this benchmark
|
|
6
|
-
regressions, not to enforce a fragile wall-clock
|
|
3
|
+
`benchmark_core.py` measures representative generic, binary, continuous, and
|
|
4
|
+
multivariable Meta-regression random-effects fits using deterministic synthetic
|
|
5
|
+
data. Correctness remains the primary performance requirement; this benchmark
|
|
6
|
+
is intended to reveal large regressions, not to enforce a fragile wall-clock
|
|
7
|
+
threshold.
|
|
7
8
|
|
|
8
9
|
Run the default benchmark with:
|
|
9
10
|
|
|
@@ -34,6 +34,8 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
|
|
|
34
34
|
|
|
35
35
|
generic_effect = rng.normal(0.1, 0.25, size=studies)
|
|
36
36
|
generic_variance = rng.uniform(0.01, 0.09, size=studies)
|
|
37
|
+
moderator = np.linspace(-1.0, 1.0, studies)
|
|
38
|
+
region = np.resize(np.array(["North", "South", "East"], dtype=object), studies)
|
|
37
39
|
|
|
38
40
|
n_treat = rng.integers(60, 240, size=studies)
|
|
39
41
|
n_control = rng.integers(60, 240, size=studies)
|
|
@@ -75,6 +77,14 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
|
|
|
75
77
|
model="random",
|
|
76
78
|
tau2_method="REML",
|
|
77
79
|
),
|
|
80
|
+
"meta_regression_multivariable_reml": lambda: ma.meta_regression(
|
|
81
|
+
effect=generic_effect,
|
|
82
|
+
variance=generic_variance,
|
|
83
|
+
moderators={"moderator": moderator, "region": region},
|
|
84
|
+
categorical={"region": ["North", "South", "East"]},
|
|
85
|
+
model="mixed",
|
|
86
|
+
tau2_method="REML",
|
|
87
|
+
),
|
|
78
88
|
}
|
|
79
89
|
|
|
80
90
|
|
|
@@ -102,8 +112,10 @@ def main() -> None:
|
|
|
102
112
|
parser.add_argument("--number", type=int, default=5)
|
|
103
113
|
parser.add_argument("--output", type=Path)
|
|
104
114
|
arguments = parser.parse_args()
|
|
105
|
-
if
|
|
106
|
-
parser.error("studies
|
|
115
|
+
if arguments.studies < 5:
|
|
116
|
+
parser.error("studies must be at least 5 for the multivariable benchmark")
|
|
117
|
+
if min(arguments.repeat, arguments.number) < 1:
|
|
118
|
+
parser.error("repeat and number must both be positive")
|
|
107
119
|
|
|
108
120
|
payload = _metadata(arguments)
|
|
109
121
|
payload["cases"] = {
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Meta-regression
|
|
2
|
+
|
|
3
|
+
Meta-regression relates study effect estimates to one or more study-level
|
|
4
|
+
moderators. It is a natural extension of subgroup analysis, but it does not
|
|
5
|
+
turn aggregate study data into individual-level evidence.
|
|
6
|
+
|
|
7
|
+
!!! warning "Interpretation boundary"
|
|
8
|
+
|
|
9
|
+
A Meta-regression coefficient is a study-level association. It may reflect
|
|
10
|
+
ecological bias, confounding, measurement differences, or post-hoc model
|
|
11
|
+
selection and must not be interpreted as an individual-level causal effect.
|
|
12
|
+
Fits with fewer than ten studies carry an explicit warning.
|
|
13
|
+
|
|
14
|
+
## Fit a numeric moderator
|
|
15
|
+
|
|
16
|
+
Provide a generic effect plus exactly one of its sampling variance or standard
|
|
17
|
+
error:
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import pandas as pd
|
|
21
|
+
import meta_analyze as ma
|
|
22
|
+
|
|
23
|
+
studies = pd.DataFrame(
|
|
24
|
+
{
|
|
25
|
+
"citation": ["A", "B", "C", "D", "E", "F"],
|
|
26
|
+
"effect": [0.12, 0.25, 0.41, 0.38, 0.62, 0.76],
|
|
27
|
+
"se": [0.18, 0.20, 0.17, 0.23, 0.19, 0.21],
|
|
28
|
+
"mean_age": [42.0, 48.0, 51.0, 55.0, 60.0, 64.0],
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
result = ma.meta_regression(
|
|
33
|
+
studies,
|
|
34
|
+
effect="effect",
|
|
35
|
+
standard_error="se",
|
|
36
|
+
moderators=["mean_age"],
|
|
37
|
+
study="citation",
|
|
38
|
+
model="mixed",
|
|
39
|
+
tau2_method="REML",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
print(result.summary())
|
|
43
|
+
print(result.coefficients)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Numeric moderators are used exactly as supplied. PyMetaAnalysis does not
|
|
47
|
+
center, scale, transform, or impute them automatically.
|
|
48
|
+
|
|
49
|
+
## Encode categorical moderators explicitly
|
|
50
|
+
|
|
51
|
+
Every categorical moderator requires an ordered, complete list of levels. The
|
|
52
|
+
first level is the treatment-coding reference:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
result = ma.meta_regression(
|
|
56
|
+
studies,
|
|
57
|
+
effect="effect",
|
|
58
|
+
standard_error="se",
|
|
59
|
+
moderators=["mean_age", "region"],
|
|
60
|
+
categorical={
|
|
61
|
+
"region": ["Europe", "Asia", "North America"],
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This produces terms such as `region[Asia]` and `region[North America]`, each
|
|
67
|
+
relative to `Europe`. The reference never depends on row order. Undeclared
|
|
68
|
+
levels, levels absent after exclusions, and string moderators omitted from
|
|
69
|
+
`categorical=` are errors rather than implicit recoding decisions.
|
|
70
|
+
|
|
71
|
+
Formula parsing, automatic interactions, splines, and polynomial terms are not
|
|
72
|
+
implemented. Construct those columns explicitly before fitting when they are
|
|
73
|
+
scientifically prespecified.
|
|
74
|
+
|
|
75
|
+
## Array-like input
|
|
76
|
+
|
|
77
|
+
Use a mapping when moderators are arrays rather than DataFrame column names:
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
result = ma.meta_regression(
|
|
81
|
+
effect=[0.10, 0.32, 0.45, 0.71],
|
|
82
|
+
variance=[0.04, 0.05, 0.06, 0.08],
|
|
83
|
+
moderators={"dose": [0.0, 1.0, 2.0, 3.0]},
|
|
84
|
+
model="common",
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
A sequence such as `moderators=["mean_age", "region"]` is only meaningful
|
|
89
|
+
with a DataFrame. A mapping may mix DataFrame column selectors and array-like
|
|
90
|
+
values, provided every input has one value per row.
|
|
91
|
+
|
|
92
|
+
## Models and inference
|
|
93
|
+
|
|
94
|
+
`model="mixed"` is the default. It estimates residual tau-squared after the
|
|
95
|
+
moderators using REML, PM, or DL. `model="common"` fixes residual tau-squared
|
|
96
|
+
at zero and supports normal inference only.
|
|
97
|
+
|
|
98
|
+
| Setting | Coefficient tests and intervals | Joint moderator test |
|
|
99
|
+
| --- | --- | --- |
|
|
100
|
+
| `normal` | z / normal | chi-squared |
|
|
101
|
+
| `hartung_knapp` | t with `k-p` df | F with `k-p` denominator df |
|
|
102
|
+
| `hartung_knapp_adhoc` | safeguarded t with `k-p` df | safeguarded F |
|
|
103
|
+
|
|
104
|
+
The unmodified Hartung-Knapp result warns when its covariance is below the
|
|
105
|
+
classic covariance. The `adhoc` choice explicitly applies a lower-bound scale
|
|
106
|
+
of one. Common-effect models reject both Hartung-Knapp choices.
|
|
107
|
+
|
|
108
|
+
The design matrix must be full rank and leave positive residual degrees of
|
|
109
|
+
freedom (`k > p`). PyMetaAnalysis does not silently drop collinear terms or use
|
|
110
|
+
a pseudo-inverse.
|
|
111
|
+
|
|
112
|
+
## Inspect the result
|
|
113
|
+
|
|
114
|
+
Meta-regression has no single pooled effect, so `MetaRegressionResult` does not
|
|
115
|
+
provide a scalar `estimate` or `ci`. Inspect its coefficient table instead:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
result.coefficients
|
|
119
|
+
result.coefficient_covariance
|
|
120
|
+
result.global_test
|
|
121
|
+
result.test_moderator("region")
|
|
122
|
+
result.heterogeneity
|
|
123
|
+
result.tau2
|
|
124
|
+
result.tau2_null
|
|
125
|
+
result.pseudo_r2
|
|
126
|
+
result.diagnostics
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`global_test` tests all non-intercept terms. `test_moderator(name)` tests every
|
|
130
|
+
encoded term belonging to that original moderator, so a multi-level category
|
|
131
|
+
receives one joint test rather than separate interpretation through dummy-term
|
|
132
|
+
p-values.
|
|
133
|
+
|
|
134
|
+
`study_results` retains every input row and contains fitted values, residuals,
|
|
135
|
+
precision weights, normalized precision weights, and leverage. A regression
|
|
136
|
+
precision weight is not a universal percentage contribution to every
|
|
137
|
+
coefficient.
|
|
138
|
+
|
|
139
|
+
## Predict at moderator values
|
|
140
|
+
|
|
141
|
+
Prediction replays the fitted numeric and categorical encoding:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
predictions = result.predict(
|
|
145
|
+
pd.DataFrame(
|
|
146
|
+
{
|
|
147
|
+
"mean_age": [50.0, 65.0],
|
|
148
|
+
"region": ["Europe", "Asia"],
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Every model returns the fitted mean and its confidence interval. Mixed-effects
|
|
155
|
+
models also return `pi_low` and `pi_high` for the distribution of true effects
|
|
156
|
+
in a new study with those moderators. The interval does not include an
|
|
157
|
+
additional, unknown sampling variance for a future observed estimate. Unknown
|
|
158
|
+
categories and missing prediction inputs are rejected.
|
|
159
|
+
|
|
160
|
+
## Plot a single numeric moderator
|
|
161
|
+
|
|
162
|
+
After installing the `plot` extra, an intercept-containing model with exactly
|
|
163
|
+
one numeric moderator can be displayed as a weighted bubble plot:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
ax = result.bubble(
|
|
167
|
+
moderator_label="Mean age (years)",
|
|
168
|
+
effect_label="Treatment effect",
|
|
169
|
+
show_confidence_interval=True,
|
|
170
|
+
show_prediction_interval=True,
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Bubble area is proportional to normalized fitted precision weight. The fitted
|
|
175
|
+
line and interval bands reuse `result.predict()`, including the selected normal
|
|
176
|
+
or Hartung-Knapp covariance and critical value. A prediction band is available
|
|
177
|
+
only for mixed-effects models.
|
|
178
|
+
|
|
179
|
+
PyMetaAnalysis rejects bubble plots for categorical, multiple-moderator, or
|
|
180
|
+
no-intercept fits. Drawing a marginal or partial-effect line for those models
|
|
181
|
+
requires explicit choices for the other moderator values, and the library does
|
|
182
|
+
not silently choose them.
|
|
183
|
+
|
|
184
|
+
## Residual heterogeneity and pseudo-R²
|
|
185
|
+
|
|
186
|
+
The result reports residual `QE`, I-squared, H-squared, and tau-squared. For an
|
|
187
|
+
intercept-containing mixed model, PyMetaAnalysis also refits the same included
|
|
188
|
+
rows without moderators and reports:
|
|
189
|
+
|
|
190
|
+
```text
|
|
191
|
+
pseudo-R² = max(0, 1 - tau²_model / tau²_null)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
The raw value is retained as `pseudo_r2_raw`. If the null-model tau-squared is
|
|
195
|
+
zero, pseudo-R² is undefined; if moderators increase estimated tau-squared,
|
|
196
|
+
the public value is truncated to zero and the negative raw value is retained
|
|
197
|
+
with a warning. Pseudo-R² is not the proportion of outcome variance explained
|
|
198
|
+
in ordinary individual-level regression.
|
|
199
|
+
|
|
200
|
+
## Missing values, provenance, and reports
|
|
201
|
+
|
|
202
|
+
`missing="raise"` identifies every missing effect, uncertainty, study label,
|
|
203
|
+
or moderator field by row. `missing="drop"` excludes the entire row from every
|
|
204
|
+
model calculation while retaining it in `study_results` with all applicable
|
|
205
|
+
reasons.
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
result.provenance
|
|
209
|
+
result.method_details()
|
|
210
|
+
result.report().to_json()
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Provenance records moderator input roles and categorical treatment coding.
|
|
214
|
+
Reports include coefficients, their covariance, residual heterogeneity,
|
|
215
|
+
moderator tests, encoding, diagnostics, row decisions, and the study-level
|
|
216
|
+
interpretation warning.
|
|
217
|
+
|
|
218
|
+
See [statistical methods](../methods/statistical-methods.md#meta-regression) for
|
|
219
|
+
the equations and [scope and limitations](../limitations.md) before using the
|
|
220
|
+
model for consequential work.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Plotting
|
|
2
2
|
|
|
3
|
-
Forest, subgroup forest, and
|
|
3
|
+
Forest, subgroup forest, funnel, and Meta-regression bubble plots use optional
|
|
4
|
+
Matplotlib support.
|
|
4
5
|
Install it with:
|
|
5
6
|
|
|
6
7
|
```console
|
|
@@ -96,6 +97,36 @@ selection, design differences, chance, or publication processes. It is not by
|
|
|
96
97
|
itself evidence of publication bias. PyMetaAnalysis currently provides the
|
|
97
98
|
plot but not formal asymmetry tests.
|
|
98
99
|
|
|
100
|
+
## Meta-regression bubble plots
|
|
101
|
+
|
|
102
|
+
An intercept-containing Meta-regression with exactly one numeric moderator
|
|
103
|
+
provides:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
ax = regression.bubble(
|
|
107
|
+
moderator_label="Dose",
|
|
108
|
+
effect_label="Effect",
|
|
109
|
+
show_confidence_interval=True,
|
|
110
|
+
show_prediction_interval=False,
|
|
111
|
+
)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Study marker area is proportional to normalized precision weight. The line,
|
|
115
|
+
mean confidence band, and optional mixed-effects true-effect prediction band
|
|
116
|
+
are obtained from the fitted model's `predict()` method.
|
|
117
|
+
|
|
118
|
+
| Parameter | Meaning |
|
|
119
|
+
| --- | --- |
|
|
120
|
+
| `ax` | Existing axes; a new one is created when omitted |
|
|
121
|
+
| `moderator_label` | X-axis label; defaults to the moderator name |
|
|
122
|
+
| `effect_label` | Y-axis label; defaults to `"Effect"` |
|
|
123
|
+
| `show_confidence_interval` | Draw the fitted mean confidence band |
|
|
124
|
+
| `show_prediction_interval` | Draw a mixed-effects true-effect prediction band |
|
|
125
|
+
|
|
126
|
+
Categorical, multivariable, and no-intercept fits are rejected because a
|
|
127
|
+
marginal plot would require values or averaging rules for other terms. The
|
|
128
|
+
function does not infer those scientific choices.
|
|
129
|
+
|
|
99
130
|
## Save or display
|
|
100
131
|
|
|
101
132
|
The caller controls rendering:
|
|
@@ -100,7 +100,7 @@ The payload contains:
|
|
|
100
100
|
- provenance and warnings;
|
|
101
101
|
- row-level study results.
|
|
102
102
|
|
|
103
|
-
Report schema 1.
|
|
103
|
+
Report schema 1.2 records the resolved heterogeneity definition as
|
|
104
104
|
`heterogeneity.i2_method`.
|
|
105
105
|
|
|
106
106
|
The complete key-level contract, including the separately versioned
|
|
@@ -18,8 +18,9 @@ effects, exclusions, weights, method choices, and diagnostics.
|
|
|
18
18
|
| Effect estimates and sampling variances | `meta_analysis()` | Generic inverse variance |
|
|
19
19
|
| Events and totals for two groups | `meta_binary()` | OR, RR, RD |
|
|
20
20
|
| Means, SDs, and sample sizes for two groups | `meta_continuous()` | MD, Hedges' g |
|
|
21
|
+
| Effect estimates, uncertainty, and study-level moderators | `meta_regression()` | Generic Meta-regression |
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
The three pooling functions accept an optional `subgroup=` column or array. Supplying
|
|
23
24
|
it returns a dedicated subgroup result containing each group, the overall
|
|
24
25
|
analysis, and a formal test for subgroup differences.
|
|
25
26
|
|
|
@@ -52,6 +53,7 @@ shows how to inspect its output. Continue with the guide matching your input:
|
|
|
52
53
|
- [generic effects and variances](guides/generic-effects.md);
|
|
53
54
|
- [binary outcomes](guides/binary-outcomes.md);
|
|
54
55
|
- [continuous outcomes](guides/continuous-outcomes.md).
|
|
56
|
+
- [study-level Meta-regression](guides/meta-regression.md).
|
|
55
57
|
|
|
56
58
|
Read [input data and row decisions](guides/input-data.md) before building a
|
|
57
59
|
pipeline around exclusions or mixed DataFrame/array inputs.
|
|
@@ -82,10 +84,11 @@ lists unsupported methods explicitly.
|
|
|
82
84
|
|
|
83
85
|
## Project status
|
|
84
86
|
|
|
85
|
-
PyMetaAnalysis 0.2.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
PyMetaAnalysis 0.2.1 fixes documentation and repository links in the PyPI
|
|
88
|
+
project description. Version 0.2.0 added direct generic standard-error input
|
|
89
|
+
to the initial public analysis scope. The project has not undergone a formal
|
|
90
|
+
external statistical audit. Pin the package version for consequential work
|
|
91
|
+
and independently check important analyses. See the repository
|
|
89
92
|
[changelog](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/CHANGELOG.md)
|
|
90
93
|
and [contribution guide](development.md). For manuscripts and archived
|
|
91
94
|
analyses, see [citing PyMetaAnalysis](citation.md).
|