PyMetaAnalysis 0.3.0__tar.gz → 0.4.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.3.0 → pymetaanalysis-0.4.0}/CHANGELOG.md +20 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/CITATION.cff +2 -2
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/PKG-INFO +29 -6
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/README.md +27 -4
- pymetaanalysis-0.4.0/docs/adr/0003-meta-regression-prediction-intervals.md +70 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/getting-started.md +1 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/meta-regression.md +149 -3
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/r-interoperability.md +12 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/sensitivity-analysis.md +82 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/zero-events.md +6 -6
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/index.md +6 -5
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/limitations.md +11 -4
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/methods/statistical-methods.md +134 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/reference/api.md +14 -4
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/reference/results.md +142 -2
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/releasing.md +9 -9
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/validation.md +17 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/mkdocs.yml +1 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/pyproject.toml +1 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/__init__.py +14 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/_version.py +1 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/regression_api.py +37 -3
- pymetaanalysis-0.4.0/src/meta_analyze/regression_collinearity.py +304 -0
- pymetaanalysis-0.4.0/src/meta_analyze/regression_contrasts.py +365 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/regression_results.py +67 -1
- pymetaanalysis-0.4.0/src/meta_analyze/regression_sensitivity.py +587 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/README.md +13 -1
- pymetaanalysis-0.4.0/tests/reference/generate_meta_regression_collinearity_metafor.R +81 -0
- pymetaanalysis-0.4.0/tests/reference/generate_meta_regression_contrasts_metafor.R +96 -0
- pymetaanalysis-0.4.0/tests/reference/generate_meta_regression_influence_metafor.R +81 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generate_meta_regression_metafor.R +39 -7
- pymetaanalysis-0.4.0/tests/reference/meta_regression_collinearity_metafor.json +65 -0
- pymetaanalysis-0.4.0/tests/reference/meta_regression_contrasts_metafor.json +157 -0
- pymetaanalysis-0.4.0/tests/reference/meta_regression_influence_metafor.json +804 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/meta_regression_metafor.json +190 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_meta_regression.py +81 -1
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_properties.py +44 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_r_references.py +88 -0
- pymetaanalysis-0.4.0/tests/test_regression_collinearity.py +288 -0
- pymetaanalysis-0.4.0/tests/test_regression_contrasts.py +346 -0
- pymetaanalysis-0.4.0/tests/test_regression_influence.py +319 -0
- pymetaanalysis-0.4.0/tests/test_regression_sensitivity.py +273 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/.github/workflows/ci.yml +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/.github/workflows/pages.yml +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/.github/workflows/release.yml +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/.gitignore +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/CONTRIBUTING.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/LICENSE +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/SECURITY.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/benchmarks/README.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/benchmarks/benchmark_core.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/adr/0001-optional-matplotlib.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/adr/0002-statistical-policy.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/citation.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/development.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/binary-outcomes.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/continuous-outcomes.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/generic-effects.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/input-data.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/method-selection.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/plotting.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/guides/provenance-reporting.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/installation.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/reference/report-schema.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/docs/stylesheets/extra.css +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/examples/README.md +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/examples/meta_regression.ipynb +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/examples/quickstart.ipynb +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/api.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/binary_api.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/config.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/continuous_api.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/data.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/design_matrix.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/effect_sizes/__init__.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/effect_sizes/binary.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/effect_sizes/continuous.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/estimators/__init__.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/estimators/inverse_variance.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/estimators/mantel_haenszel.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/estimators/meta_regression.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/estimators/tau2.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/exceptions.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/heterogeneity.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/__init__.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/_utils.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/forest.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/funnel.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/regression.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/plotting/subgroup_forest.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/provenance.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/py.typed +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/reporting.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/results.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/sensitivity.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/src/meta_analyze/subgroups.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/binary_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/binary_metafor.json +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/binary_sparse_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/continuous_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/continuous_metafor.json +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generate_binary_metafor.R +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generate_continuous_metafor.R +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generate_generic_metafor.R +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generate_workflow_metafor.R +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generic_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/generic_metafor.json +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/meta_regression_boundary_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/meta_regression_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/workflow_input.csv +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/reference/workflow_metafor.json +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_api.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_binary.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_continuous.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_documentation.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_estimators.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_funnel_plot.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_numerical_stability.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_plotting.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_reference_results.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_regression_plotting.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_release_readiness.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_reporting.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_sensitivity.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tests/test_subgroups.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tools/check_release.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tools/execute_notebooks.py +0 -0
- {pymetaanalysis-0.3.0 → pymetaanalysis-0.4.0}/tools/inspect_distribution.py +0 -0
|
@@ -6,6 +6,26 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.4.0 - 2026-07-23
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- leave-one-out Meta-regression refits with model-level diagnostics,
|
|
14
|
+
coefficient changes, explicit unidentifiable-deletion records, and preserved
|
|
15
|
+
provenance.
|
|
16
|
+
- exact Meta-regression externally standardized residuals, Cook's distances,
|
|
17
|
+
DFBETAS, transparent screening thresholds, and fixed-version R `metafor`
|
|
18
|
+
cross-software fixtures.
|
|
19
|
+
- Meta-regression term VIF, moderator-level GVIF/GSIF, and weighted,
|
|
20
|
+
column-scaled condition diagnostics with variance-decomposition proportions,
|
|
21
|
+
heuristic-only flags, and R `metafor` cross-software fixtures.
|
|
22
|
+
- explicit named Meta-regression linear contrasts with nonzero null values,
|
|
23
|
+
individual z/t inference, joint chi-squared/F tests, labeled coefficient
|
|
24
|
+
matrices, and R `metafor` cross-software fixtures.
|
|
25
|
+
- opt-in Riley Meta-regression true-effect prediction intervals using
|
|
26
|
+
`t_(k-p-1)`, with explicit residual-df validation, preserved refit
|
|
27
|
+
configuration, and fixed-version R `metafor` boundary references.
|
|
28
|
+
|
|
9
29
|
## 0.3.0 - 2026-07-22
|
|
10
30
|
|
|
11
31
|
### 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.4.0
|
|
12
|
+
date-released: 2026-07-23
|
|
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.4.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
|
|
@@ -28,7 +28,7 @@ Requires-Dist: actionlint-py>=1.7.12.24; extra == 'dev'
|
|
|
28
28
|
Requires-Dist: build>=1.2; extra == 'dev'
|
|
29
29
|
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
30
30
|
Requires-Dist: pandas-stubs>=2.0; extra == 'dev'
|
|
31
|
-
Requires-Dist: ruff
|
|
31
|
+
Requires-Dist: ruff<0.17,>=0.16; extra == 'dev'
|
|
32
32
|
Requires-Dist: scipy-stubs>=1.10; extra == 'dev'
|
|
33
33
|
Provides-Extra: docs
|
|
34
34
|
Requires-Dist: mkdocs>=1.6; extra == 'docs'
|
|
@@ -177,11 +177,23 @@ Rows excluded by missing-value or sparse-data policies remain in
|
|
|
177
177
|
`study_results` with a stable `row_id`, `included=False`, and an
|
|
178
178
|
`exclusion_reason`.
|
|
179
179
|
|
|
180
|
-
##
|
|
180
|
+
## Diagnostics, contrasts, and plots
|
|
181
181
|
|
|
182
182
|
```python
|
|
183
183
|
leave_one_out = result.leave_one_out().to_dataframe()
|
|
184
184
|
cumulative = result.cumulative(order="publication_year").to_dataframe()
|
|
185
|
+
regression_deleted = regression.leave_one_out()
|
|
186
|
+
regression_coefficient_changes = regression_deleted.coefficients
|
|
187
|
+
regression_influence = regression.influence()
|
|
188
|
+
flagged_diagnostics = regression_influence.flagged
|
|
189
|
+
collinearity = regression.collinearity()
|
|
190
|
+
term_vif = collinearity.term_vif
|
|
191
|
+
moderator_gvif = collinearity.moderator_gvif
|
|
192
|
+
condition_indices = collinearity.condition_indices
|
|
193
|
+
south_vs_east = regression.contrast(
|
|
194
|
+
{"region[South]": 1.0, "region[East]": -1.0},
|
|
195
|
+
name="South - East",
|
|
196
|
+
)
|
|
185
197
|
|
|
186
198
|
ax = result.forest(show_prediction_interval=True)
|
|
187
199
|
ax = result.funnel()
|
|
@@ -189,9 +201,20 @@ ax = result.funnel()
|
|
|
189
201
|
|
|
190
202
|
Plotting methods return Matplotlib axes and never call `show()`. Funnel plots
|
|
191
203
|
are descriptive small-study-effect diagnostics, not proof of publication bias.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
204
|
+
Meta-regression leave-one-out results also expose a long-form coefficient
|
|
205
|
+
change table. Exact influence diagnostics add externally standardized
|
|
206
|
+
residuals, Cook's distance, DFBETAS, and explicit heuristic screening
|
|
207
|
+
thresholds without automatically excluding studies. Meta-regression
|
|
208
|
+
collinearity diagnostics add `metafor`-compatible VIF/GVIF plus weighted,
|
|
209
|
+
column-scaled condition indices and variance-decomposition proportions.
|
|
210
|
+
Their documented references are review aids, not automatic variable-selection
|
|
211
|
+
rules. Explicit named linear contrasts provide individual z/t inference and
|
|
212
|
+
full-rank joint chi-squared/F tests without silently adjusting for multiple
|
|
213
|
+
testing. An eligible
|
|
214
|
+
single-numeric-moderator Meta-regression result additionally provides
|
|
215
|
+
`regression.bubble()` with fitted confidence and optional prediction bands.
|
|
216
|
+
Mixed-effects Meta-regression supports its documented default prediction rule
|
|
217
|
+
and an explicit Riley `t_(k-p-1)` alternative.
|
|
195
218
|
|
|
196
219
|
## Documentation
|
|
197
220
|
|
|
@@ -128,11 +128,23 @@ Rows excluded by missing-value or sparse-data policies remain in
|
|
|
128
128
|
`study_results` with a stable `row_id`, `included=False`, and an
|
|
129
129
|
`exclusion_reason`.
|
|
130
130
|
|
|
131
|
-
##
|
|
131
|
+
## Diagnostics, contrasts, and plots
|
|
132
132
|
|
|
133
133
|
```python
|
|
134
134
|
leave_one_out = result.leave_one_out().to_dataframe()
|
|
135
135
|
cumulative = result.cumulative(order="publication_year").to_dataframe()
|
|
136
|
+
regression_deleted = regression.leave_one_out()
|
|
137
|
+
regression_coefficient_changes = regression_deleted.coefficients
|
|
138
|
+
regression_influence = regression.influence()
|
|
139
|
+
flagged_diagnostics = regression_influence.flagged
|
|
140
|
+
collinearity = regression.collinearity()
|
|
141
|
+
term_vif = collinearity.term_vif
|
|
142
|
+
moderator_gvif = collinearity.moderator_gvif
|
|
143
|
+
condition_indices = collinearity.condition_indices
|
|
144
|
+
south_vs_east = regression.contrast(
|
|
145
|
+
{"region[South]": 1.0, "region[East]": -1.0},
|
|
146
|
+
name="South - East",
|
|
147
|
+
)
|
|
136
148
|
|
|
137
149
|
ax = result.forest(show_prediction_interval=True)
|
|
138
150
|
ax = result.funnel()
|
|
@@ -140,9 +152,20 @@ ax = result.funnel()
|
|
|
140
152
|
|
|
141
153
|
Plotting methods return Matplotlib axes and never call `show()`. Funnel plots
|
|
142
154
|
are descriptive small-study-effect diagnostics, not proof of publication bias.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
Meta-regression leave-one-out results also expose a long-form coefficient
|
|
156
|
+
change table. Exact influence diagnostics add externally standardized
|
|
157
|
+
residuals, Cook's distance, DFBETAS, and explicit heuristic screening
|
|
158
|
+
thresholds without automatically excluding studies. Meta-regression
|
|
159
|
+
collinearity diagnostics add `metafor`-compatible VIF/GVIF plus weighted,
|
|
160
|
+
column-scaled condition indices and variance-decomposition proportions.
|
|
161
|
+
Their documented references are review aids, not automatic variable-selection
|
|
162
|
+
rules. Explicit named linear contrasts provide individual z/t inference and
|
|
163
|
+
full-rank joint chi-squared/F tests without silently adjusting for multiple
|
|
164
|
+
testing. An eligible
|
|
165
|
+
single-numeric-moderator Meta-regression result additionally provides
|
|
166
|
+
`regression.bubble()` with fitted confidence and optional prediction bands.
|
|
167
|
+
Mixed-effects Meta-regression supports its documented default prediction rule
|
|
168
|
+
and an explicit Riley `t_(k-p-1)` alternative.
|
|
146
169
|
|
|
147
170
|
## Documentation
|
|
148
171
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# ADR 0003: Meta-regression prediction-interval choices
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-07-23
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
For a mixed-effects Meta-regression prediction at design vector `x`, the
|
|
9
|
+
estimated true-effect variance combines residual heterogeneity with
|
|
10
|
+
uncertainty in the fitted mean:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
Var_prediction = tau^2 + x' Cov(beta_hat) x
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The critical-value distribution remains a methodological choice. Common
|
|
17
|
+
software offers a default normal-or-t rule and a Riley alternative with one
|
|
18
|
+
fewer residual degree of freedom. Neither approximation removes uncertainty
|
|
19
|
+
from estimating tau-squared, and changing the package default would alter
|
|
20
|
+
existing results.
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
`meta_regression()` accepts
|
|
25
|
+
`prediction_interval_method="default" | "riley"` for mixed-effects models.
|
|
26
|
+
The canonical resolved method is stored in
|
|
27
|
+
`result.method.prediction_interval_method`.
|
|
28
|
+
|
|
29
|
+
The default remains `normal_or_t_k_minus_p`:
|
|
30
|
+
|
|
31
|
+
- normal coefficient inference uses a standard normal prediction critical
|
|
32
|
+
value;
|
|
33
|
+
- either Hartung-Knapp mode uses a t critical value with `k-p` degrees of
|
|
34
|
+
freedom.
|
|
35
|
+
|
|
36
|
+
The opt-in Riley method uses a t critical value with `k-p-1` degrees of
|
|
37
|
+
freedom regardless of the coefficient-inference distribution:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
prediction = x' beta_hat
|
|
41
|
+
PI_Riley = prediction +/- t_(k-p-1) *
|
|
42
|
+
sqrt(tau^2 + x' Cov(beta_hat) x)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Riley intervals require `k-p >= 2`. Requesting Riley for a common-effect model
|
|
46
|
+
or a mixed model without enough residual degrees of freedom raises a domain
|
|
47
|
+
error. The selection is preserved by deleted-study refits and reused by
|
|
48
|
+
`predict()` and `bubble()`.
|
|
49
|
+
|
|
50
|
+
Both rules predict the distribution of true effects in a new study at the
|
|
51
|
+
specified moderator values. They do not add an unknown sampling variance for
|
|
52
|
+
a future observed effect.
|
|
53
|
+
|
|
54
|
+
## Validation
|
|
55
|
+
|
|
56
|
+
The committed fixed-version R `metafor` fixture records default and
|
|
57
|
+
`predtype="Riley"` predictions for normal and Hartung-Knapp inference,
|
|
58
|
+
multivariable moderator values, and a zero-tau-squared boundary. Unit tests
|
|
59
|
+
also check the critical-value formula and invalid degrees of freedom.
|
|
60
|
+
Property-based tests verify symmetry, unchanged mean-effect inference, and
|
|
61
|
+
the Riley interval's greater width relative to the default rule.
|
|
62
|
+
|
|
63
|
+
## Consequences
|
|
64
|
+
|
|
65
|
+
- existing fits retain their numerical default;
|
|
66
|
+
- the alternative is explicit, auditable, and reproducible;
|
|
67
|
+
- Riley is documented as an alternative approximation rather than an
|
|
68
|
+
automatic small-sample correction;
|
|
69
|
+
- future prediction-interval rules require a separate statistical decision
|
|
70
|
+
and independent reference coverage.
|
|
@@ -136,6 +136,23 @@ precision weights, normalized precision weights, and leverage. A regression
|
|
|
136
136
|
precision weight is not a universal percentage contribution to every
|
|
137
137
|
coefficient.
|
|
138
138
|
|
|
139
|
+
## Leave-one-out sensitivity
|
|
140
|
+
|
|
141
|
+
Use exact deleted-model refits to inspect dependence on individual studies:
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
diagnostics = result.leave_one_out()
|
|
145
|
+
|
|
146
|
+
print(diagnostics.table)
|
|
147
|
+
print(diagnostics.coefficients)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Every successful deletion re-estimates residual tau-squared, coefficients, and
|
|
151
|
+
inference with the same resolved model configuration. Deletions that make the
|
|
152
|
+
design unidentifiable are retained explicitly instead of aborting the other
|
|
153
|
+
refits. See [sensitivity analysis](sensitivity-analysis.md) for the result
|
|
154
|
+
contract and interpretation limits.
|
|
155
|
+
|
|
139
156
|
## Predict at moderator values
|
|
140
157
|
|
|
141
158
|
Prediction replays the fitted numeric and categorical encoding:
|
|
@@ -157,6 +174,16 @@ in a new study with those moderators. The interval does not include an
|
|
|
157
174
|
additional, unknown sampling variance for a future observed estimate. Unknown
|
|
158
175
|
categories and missing prediction inputs are rejected.
|
|
159
176
|
|
|
177
|
+
The default prediction rule follows coefficient inference: it uses a normal
|
|
178
|
+
critical value with `inference_method="normal"` and `t_(k-p)` with either
|
|
179
|
+
Hartung-Knapp method. Set `prediction_interval_method="riley"` while fitting to
|
|
180
|
+
use a `t_(k-p-1)` prediction critical value instead. Riley therefore needs at
|
|
181
|
+
least two residual degrees of freedom and is usually wider, especially in
|
|
182
|
+
small samples. It is an explicit alternative approximation, not an automatic
|
|
183
|
+
claim of superior coverage. The selected canonical method is retained in
|
|
184
|
+
`result.method.prediction_interval_method` and reused by `predict()` and
|
|
185
|
+
`bubble()`.
|
|
186
|
+
|
|
160
187
|
## Plot a single numeric moderator
|
|
161
188
|
|
|
162
189
|
After installing the `plot` extra, an intercept-containing model with exactly
|
|
@@ -172,9 +199,9 @@ ax = result.bubble(
|
|
|
172
199
|
```
|
|
173
200
|
|
|
174
201
|
Bubble area is proportional to normalized fitted precision weight. The fitted
|
|
175
|
-
line and interval bands reuse `result.predict()`, including the selected
|
|
176
|
-
|
|
177
|
-
only for mixed-effects models.
|
|
202
|
+
line and interval bands reuse `result.predict()`, including the selected
|
|
203
|
+
coefficient covariance and prediction-interval rule. A prediction band is
|
|
204
|
+
available only for mixed-effects models.
|
|
178
205
|
|
|
179
206
|
PyMetaAnalysis rejects bubble plots for categorical, multiple-moderator, or
|
|
180
207
|
no-intercept fits. Drawing a marginal or partial-effect line for those models
|
|
@@ -197,6 +224,125 @@ the public value is truncated to zero and the negative raw value is retained
|
|
|
197
224
|
with a warning. Pseudo-R² is not the proportion of outcome variance explained
|
|
198
225
|
in ordinary individual-level regression.
|
|
199
226
|
|
|
227
|
+
## Inspect deleted-study influence
|
|
228
|
+
|
|
229
|
+
Use exact deletion diagnostics when a study appears unusual or the fitted
|
|
230
|
+
association may depend strongly on one row:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
influence = result.influence()
|
|
234
|
+
|
|
235
|
+
influence.table
|
|
236
|
+
influence.dfbetas
|
|
237
|
+
influence.flagged
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Every included study is omitted once, with tau-squared and coefficient
|
|
241
|
+
inference re-estimated under the original settings. The result reports the
|
|
242
|
+
externally standardized deleted residual, Cook's distance, and term-specific
|
|
243
|
+
DFBETAS values. Failed reduced models remain visible rather than being silently
|
|
244
|
+
dropped.
|
|
245
|
+
|
|
246
|
+
The result also exposes its numerical screening thresholds. These thresholds
|
|
247
|
+
identify rows for review; they do not prove that a study is erroneous,
|
|
248
|
+
authorize automatic exclusion, or correct for trying multiple model
|
|
249
|
+
specifications. See [sensitivity analysis](sensitivity-analysis.md) for the
|
|
250
|
+
full output and interpretation contract.
|
|
251
|
+
|
|
252
|
+
## Inspect moderator collinearity
|
|
253
|
+
|
|
254
|
+
Use `collinearity()` to inspect coefficient inflation and the geometry of the
|
|
255
|
+
fitted weighted design:
|
|
256
|
+
|
|
257
|
+
```python
|
|
258
|
+
collinearity = result.collinearity()
|
|
259
|
+
|
|
260
|
+
collinearity.term_vif
|
|
261
|
+
collinearity.moderator_gvif
|
|
262
|
+
collinearity.condition_indices
|
|
263
|
+
collinearity.variance_proportions
|
|
264
|
+
collinearity.concerning_dimensions
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`term_vif` contains one VIF and its square-root standard-error inflation factor
|
|
268
|
+
(`sif`) for every encoded non-intercept term. `moderator_gvif` keeps all dummy
|
|
269
|
+
terms for one categorical moderator together and reports its GVIF plus the
|
|
270
|
+
dimension-adjusted `gsif = gvif ** (1 / (2 * term_count))`. This grouping makes
|
|
271
|
+
a multi-level moderator comparable without pretending that each treatment-
|
|
272
|
+
coded term is a separate scientific variable.
|
|
273
|
+
|
|
274
|
+
The condition table uses the fitted inverse-variance weights and normalizes
|
|
275
|
+
each weighted design column before singular-value decomposition. It is
|
|
276
|
+
therefore invariant to positive changes of moderator units. The result retains
|
|
277
|
+
the original unweighted, scale-dependent design condition number separately as
|
|
278
|
+
`raw_condition_number`.
|
|
279
|
+
|
|
280
|
+
The fixed references of condition index greater than 30 and variance
|
|
281
|
+
proportion greater than 0.5 are conventional screening heuristics. A
|
|
282
|
+
`concerning` dimension must meet the condition-index reference and concentrate
|
|
283
|
+
more than half of the coefficient variance for at least two terms. The library
|
|
284
|
+
does not attach automatic cutoffs to VIF/GVIF, remove variables, refit models,
|
|
285
|
+
or turn these diagnostics into evidence for a preferred specification.
|
|
286
|
+
|
|
287
|
+
## Test explicit linear contrasts
|
|
288
|
+
|
|
289
|
+
Inspect `result.design_info.term_names`, then define a scientific comparison by
|
|
290
|
+
term name rather than coefficient position:
|
|
291
|
+
|
|
292
|
+
```python
|
|
293
|
+
south_vs_east = result.contrast(
|
|
294
|
+
{
|
|
295
|
+
"region[South]": 1.0,
|
|
296
|
+
"region[East]": -1.0,
|
|
297
|
+
},
|
|
298
|
+
name="South - East",
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
south_vs_east.table
|
|
302
|
+
south_vs_east.contrast_matrix
|
|
303
|
+
south_vs_east.joint_test
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The default null hypothesis is `C beta = 0`. Use `rhs=` for a nonzero null:
|
|
307
|
+
|
|
308
|
+
```python
|
|
309
|
+
age_threshold = result.contrast(
|
|
310
|
+
{"mean_age": 1.0},
|
|
311
|
+
name="Age slope equals 0.02",
|
|
312
|
+
rhs=0.02,
|
|
313
|
+
)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
For several prespecified hypotheses, pass a named mapping of mappings:
|
|
317
|
+
|
|
318
|
+
```python
|
|
319
|
+
contrasts = result.contrast(
|
|
320
|
+
{
|
|
321
|
+
"South - East": {
|
|
322
|
+
"region[South]": 1.0,
|
|
323
|
+
"region[East]": -1.0,
|
|
324
|
+
},
|
|
325
|
+
"Age slope": {"mean_age": 1.0},
|
|
326
|
+
},
|
|
327
|
+
rhs={
|
|
328
|
+
"South - East": 0.0,
|
|
329
|
+
"Age slope": 0.02,
|
|
330
|
+
},
|
|
331
|
+
)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
A DataFrame is also accepted: rows are named contrasts and columns are fitted
|
|
335
|
+
term names. Unspecified fitted terms receive weight zero. Unknown terms,
|
|
336
|
+
nonfinite weights, zero rows, duplicate names, and rank-deficient multi-row
|
|
337
|
+
contrast matrices are errors rather than implicit repairs.
|
|
338
|
+
|
|
339
|
+
Each row reports the contrast estimate, standard error, null value,
|
|
340
|
+
estimate-minus-null, z or t statistic, unadjusted p-value, and confidence
|
|
341
|
+
interval for `C beta`. A full-row-rank set also receives a joint chi-squared or
|
|
342
|
+
F test in `joint_test`. Individual p-values are deliberately not adjusted for
|
|
343
|
+
multiple testing; prespecify the contrast family and apply an external
|
|
344
|
+
multiplicity procedure when the scientific protocol requires one.
|
|
345
|
+
|
|
200
346
|
## Missing values, provenance, and reports
|
|
201
347
|
|
|
202
348
|
`missing="raise"` identifies every missing effect, uncertainty, study label,
|
|
@@ -19,6 +19,9 @@ fixtures used by this project.
|
|
|
19
19
|
| Continuous group summaries | `meta_continuous()` | `escalc()` then `rma.uni()` | `metacont()` |
|
|
20
20
|
| Subgroups | `subgroup=` on a high-level call | separate fits or a moderator model | `subgroup=` |
|
|
21
21
|
| Leave-one-out | `result.leave_one_out()` | `leave1out()` for supported fits | `metainf()` |
|
|
22
|
+
| Meta-regression influence | `regression.influence()` | `influence()`, `rstudent()`, `cooks.distance()`, `dfbetas()` | — |
|
|
23
|
+
| Meta-regression collinearity | `regression.collinearity()` | `vif()` plus weighted design diagnostics | — |
|
|
24
|
+
| Meta-regression linear contrasts | `regression.contrast(...)` | `anova(..., X=..., rhs=...)` | — |
|
|
22
25
|
| Cumulative analysis | `result.cumulative()` | `cumul()` | `metacum()` |
|
|
23
26
|
|
|
24
27
|
PyMetaAnalysis intentionally has no `metabin`, `metacont`, or `rma` aliases.
|
|
@@ -88,6 +91,14 @@ Eligible random-effects fits include the documented HTS prediction interval.
|
|
|
88
91
|
R packages offer additional prediction-interval choices, so matching the mean
|
|
89
92
|
interval does not by itself guarantee a matching prediction interval.
|
|
90
93
|
|
|
94
|
+
Meta-regression uses a separate prediction rule. Its default corresponds to
|
|
95
|
+
`predict(fit)` in `metafor`: normal inference uses a normal critical value and
|
|
96
|
+
Hartung-Knapp inference uses `t_(k-p)`. PyMetaAnalysis
|
|
97
|
+
`prediction_interval_method="riley"` corresponds to
|
|
98
|
+
`predict(fit, predtype="Riley")`, using `t_(k-p-1)` for the true-effect
|
|
99
|
+
prediction interval while leaving the mean-effect confidence interval
|
|
100
|
+
unchanged.
|
|
101
|
+
|
|
91
102
|
## Sparse binary studies
|
|
92
103
|
|
|
93
104
|
The closest names are:
|
|
@@ -171,6 +182,7 @@ as numerically equivalent.
|
|
|
171
182
|
## Primary R references
|
|
172
183
|
|
|
173
184
|
- [`metafor::rma.uni`](https://wviechtb.github.io/metafor/reference/rma.uni.html)
|
|
185
|
+
- [`metafor::predict.rma`](https://wviechtb.github.io/metafor/reference/predict.rma.html)
|
|
174
186
|
- [`metafor::rma.mh`](https://wviechtb.github.io/metafor/reference/rma.mh.html)
|
|
175
187
|
- [`metafor::escalc`](https://wviechtb.github.io/metafor/reference/escalc.html)
|
|
176
188
|
- [`meta::metagen`](https://search.r-project.org/CRAN/refmans/meta/html/metagen.html)
|
|
@@ -31,6 +31,81 @@ requires at least two included studies so each refit retains one. Random-effects
|
|
|
31
31
|
analysis requires at least three so every refit retains the two studies needed
|
|
32
32
|
to estimate tau-squared.
|
|
33
33
|
|
|
34
|
+
### Meta-regression leave-one-out analysis
|
|
35
|
+
|
|
36
|
+
`MetaRegressionResult.leave_one_out()` repeats the fitted regression while
|
|
37
|
+
omitting each included study:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
diagnostics = regression.leave_one_out()
|
|
41
|
+
|
|
42
|
+
print(diagnostics.table)
|
|
43
|
+
print(diagnostics.coefficients)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The returned `MetaRegressionLeaveOneOutResult` retains `original` and a
|
|
47
|
+
`results` tuple aligned with the omitted-study rows. Its model table reports
|
|
48
|
+
the refitted residual heterogeneity, global moderator test, condition number,
|
|
49
|
+
and warnings. Its long-form coefficient table reports every refitted term and
|
|
50
|
+
`estimate_change`, defined as the deleted estimate minus the full-model
|
|
51
|
+
estimate.
|
|
52
|
+
|
|
53
|
+
Deleting a study can make a categorical level disappear or otherwise make the
|
|
54
|
+
design matrix unidentifiable. That deletion is retained with
|
|
55
|
+
`refit_success=False`, an exception type and message, unavailable numeric
|
|
56
|
+
fields, and `None` in the matching `results` position. Other deletions continue
|
|
57
|
+
to be fitted. Use `diagnostics.failed` to inspect these rows. A failed deletion
|
|
58
|
+
does not by itself label that study as influential; it shows that the fitted
|
|
59
|
+
design depends on the study for identifiability.
|
|
60
|
+
|
|
61
|
+
The original model must have at least `k >= p + 2`, so deleting one study can
|
|
62
|
+
still leave more studies than coefficients. Each successful refit re-estimates
|
|
63
|
+
tau-squared and coefficient inference with the original model settings.
|
|
64
|
+
|
|
65
|
+
### Meta-regression influence diagnostics
|
|
66
|
+
|
|
67
|
+
`MetaRegressionResult.influence()` builds on the same exact deleted-model
|
|
68
|
+
refits:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
influence = regression.influence()
|
|
72
|
+
|
|
73
|
+
print(influence.table)
|
|
74
|
+
print(influence.dfbetas)
|
|
75
|
+
print(influence.flagged)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`MetaRegressionInfluenceResult` contains the underlying `leave_one_out`
|
|
79
|
+
workflow and its omission-aligned `results`. The case-level `table` adds:
|
|
80
|
+
|
|
81
|
+
- the deleted residual, its standard error, and the externally standardized
|
|
82
|
+
residual;
|
|
83
|
+
- Cook's distance based on the full-model coefficient covariance;
|
|
84
|
+
- the largest absolute DFBETAS value across fitted terms;
|
|
85
|
+
- the original leverage and normalized precision weight;
|
|
86
|
+
- separate outlier and influence screening flags.
|
|
87
|
+
|
|
88
|
+
The long-form `dfbetas` table records the unstandardized `dfbeta` as
|
|
89
|
+
full-model minus deleted-model coefficient, its deletion-based standard-error
|
|
90
|
+
reference, the resulting DFBETAS value, and its threshold flag for each term.
|
|
91
|
+
Failed deletion fits retain their exception type and message in `table`, use
|
|
92
|
+
`NaN` diagnostics, and retain one unavailable row per term in `dfbetas`.
|
|
93
|
+
|
|
94
|
+
The screening references are explicit in both the result attributes and table:
|
|
95
|
+
|
|
96
|
+
- `abs(externally_standardized_residual) > z(0.975)` is a pointwise,
|
|
97
|
+
asymptotic potential-outlier reference;
|
|
98
|
+
- Cook's distance is flagged above the median of a chi-squared distribution
|
|
99
|
+
with `p` degrees of freedom;
|
|
100
|
+
- `abs(DFBETAS) > 1` flags a coefficient-specific change.
|
|
101
|
+
|
|
102
|
+
`potentially_influential` combines only the Cook's-distance and DFBETAS rules;
|
|
103
|
+
`flagged` also includes the residual outlier screen. These cutoffs are
|
|
104
|
+
heuristic diagnostics, not hypothesis-test conclusions, multiplicity-adjusted
|
|
105
|
+
decision rules, or instructions to exclude a study. Inspect subject-matter
|
|
106
|
+
differences, data quality, protocol decisions, and model specification before
|
|
107
|
+
acting on them.
|
|
108
|
+
|
|
34
109
|
## Cumulative analysis
|
|
35
110
|
|
|
36
111
|
By default, cumulative analysis follows input order:
|
|
@@ -80,6 +155,9 @@ Every refit reuses the original result's:
|
|
|
80
155
|
- binary continuity corrections and RD zero-variance policy, or the continuous
|
|
81
156
|
effect-size convention.
|
|
82
157
|
|
|
158
|
+
Meta-regression refits additionally reuse the intercept choice, inference
|
|
159
|
+
method, moderator order, and complete explicit categorical level definitions.
|
|
160
|
+
|
|
83
161
|
Derived results retain provenance that maps their local calculations back to
|
|
84
162
|
the original `row_id` values.
|
|
85
163
|
|
|
@@ -106,3 +184,7 @@ design, outcome definition, risk of bias, and numerical leverage. They are not
|
|
|
106
184
|
by themselves a reason to exclude the study. Likewise, a cumulative trend can
|
|
107
185
|
describe the historical evidence path but does not remove time-related changes
|
|
108
186
|
in methods, populations, or publication processes.
|
|
187
|
+
|
|
188
|
+
The current Meta-regression workflow reports exact deleted-model fits and
|
|
189
|
+
coefficient changes. It does not yet calculate Cook's distance, DFBETAS, or an
|
|
190
|
+
automatic influential-study flag.
|
|
@@ -9,8 +9,8 @@ corrections from the pooled Mantel-Haenszel correction.
|
|
|
9
9
|
For study-level OR/RR effects, the default settings are:
|
|
10
10
|
|
|
11
11
|
```python
|
|
12
|
-
continuity_correction=0.5
|
|
13
|
-
correction_scope="only_zero_studies"
|
|
12
|
+
continuity_correction = 0.5
|
|
13
|
+
correction_scope = "only_zero_studies"
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
The correction is added to every cell of an included study containing at least
|
|
@@ -43,7 +43,7 @@ variance. This includes double-zero, double-all, and opposite-boundary tables.
|
|
|
43
43
|
The default policy retains these studies:
|
|
44
44
|
|
|
45
45
|
```python
|
|
46
|
-
rd_zero_variance="correct"
|
|
46
|
+
rd_zero_variance = "correct"
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
The RD itself remains the raw treatment risk minus control risk. Corrected
|
|
@@ -51,7 +51,7 @@ counts are used only to form a positive sampling variance. To exclude all such
|
|
|
51
51
|
studies before pooling, Q, tau-squared, and weight calculations, use:
|
|
52
52
|
|
|
53
53
|
```python
|
|
54
|
-
rd_zero_variance="exclude"
|
|
54
|
+
rd_zero_variance = "exclude"
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
Excluded rows remain in `result.study_results` with
|
|
@@ -63,8 +63,8 @@ RD-specific; setting `exclude` for OR or RR is rejected.
|
|
|
63
63
|
Exact common-effect Mantel-Haenszel OR/RR pooling uses raw tables by default:
|
|
64
64
|
|
|
65
65
|
```python
|
|
66
|
-
mh_continuity_correction=None
|
|
67
|
-
mh_correction_scope="only_zero_studies"
|
|
66
|
+
mh_continuity_correction = None
|
|
67
|
+
mh_correction_scope = "only_zero_studies"
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
`continuity_correction` still controls the study-level effects used for display
|
|
@@ -84,11 +84,12 @@ lists unsupported methods explicitly.
|
|
|
84
84
|
|
|
85
85
|
## Project status
|
|
86
86
|
|
|
87
|
-
PyMetaAnalysis 0.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
external statistical audit. Pin the package version for
|
|
91
|
-
and independently check important analyses. See the
|
|
87
|
+
PyMetaAnalysis 0.4.0 extends Meta-regression with exact leave-one-out and
|
|
88
|
+
influence diagnostics, VIF/GVIF and weighted condition diagnostics, explicit
|
|
89
|
+
linear contrasts, and opt-in Riley prediction intervals. The project has not
|
|
90
|
+
undergone a formal external statistical audit. Pin the package version for
|
|
91
|
+
consequential work and independently check important analyses. See the
|
|
92
|
+
repository
|
|
92
93
|
[changelog](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/CHANGELOG.md)
|
|
93
94
|
and [contribution guide](development.md). For manuscripts and archived
|
|
94
95
|
analyses, see [citing PyMetaAnalysis](citation.md).
|
|
@@ -19,22 +19,29 @@ deferred functionality explicit.
|
|
|
19
19
|
- forest and descriptive funnel plots;
|
|
20
20
|
- structured provenance and reports;
|
|
21
21
|
- study-level Meta-regression with numeric and explicitly encoded categorical
|
|
22
|
-
moderators, generalized DL/PM/REML,
|
|
22
|
+
moderators, generalized DL/PM/REML, normal/Hartung-Knapp inference, and
|
|
23
|
+
exact leave-one-out refits plus externally standardized residual, Cook's
|
|
24
|
+
distance, DFBETAS, VIF/GVIF, weighted condition diagnostics, and explicit
|
|
25
|
+
linear contrasts;
|
|
26
|
+
- default normal/`t_(k-p)` and opt-in Riley `t_(k-p-1)` true-effect
|
|
27
|
+
prediction intervals for mixed-effects Meta-regression.
|
|
23
28
|
|
|
24
29
|
## Not currently implemented
|
|
25
30
|
|
|
26
31
|
- Peto odds ratios;
|
|
27
32
|
- Mantel-Haenszel risk differences or random-effects MH pooling;
|
|
28
33
|
- formula parsing, automatic interactions/splines, stepwise moderator
|
|
29
|
-
selection,
|
|
34
|
+
selection, automatic pairwise contrasts, or multiplicity correction;
|
|
30
35
|
- multilevel, multivariate, network, dose-response, diagnostic-accuracy, or
|
|
31
36
|
individual-participant-data meta-analysis;
|
|
32
37
|
- robust variance estimation or dependent-effect clustering;
|
|
33
38
|
- single proportions, incidence rates, correlations, or survival outcomes;
|
|
34
39
|
- Knapp-Hartung variants beyond the two documented choices;
|
|
35
|
-
-
|
|
40
|
+
- prediction-interval methods beyond the documented default and Riley rules;
|
|
36
41
|
- formal funnel-asymmetry, trim-and-fill, selection-model, or publication-bias
|
|
37
42
|
procedures;
|
|
43
|
+
- Meta-regression DFFITS, covariance ratios, influence plots, or simulated and
|
|
44
|
+
re-estimated VIF variants;
|
|
38
45
|
- automatic conversion from confidence intervals, p-values, or raw papers to
|
|
39
46
|
study effects;
|
|
40
47
|
- risk-of-bias assessment, certainty grading, protocol management, or study
|
|
@@ -78,7 +85,7 @@ workflow must version those artifacts separately.
|
|
|
78
85
|
|
|
79
86
|
## Stability and review status
|
|
80
87
|
|
|
81
|
-
The package version is currently `0.
|
|
88
|
+
The package version is currently `0.4.0`. Public APIs and serialized schemas
|
|
82
89
|
may change during the 0.x series. Pin versions in analysis environments and
|
|
83
90
|
inspect changelog/schema updates before upgrading.
|
|
84
91
|
|