PyMetaAnalysis 0.4.0__tar.gz → 0.5.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.4.0 → pymetaanalysis-0.5.0}/.github/workflows/ci.yml +1 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/.github/workflows/pages.yml +1 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/.github/workflows/release.yml +7 -3
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/CHANGELOG.md +79 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/CITATION.cff +2 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/PKG-INFO +7 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/README.md +5 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/adr/0002-statistical-policy.md +7 -4
- pymetaanalysis-0.5.0/docs/adr/0004-hartung-knapp-prediction-intervals.md +46 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/input-data.md +18 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/meta-regression.md +4 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/method-selection.md +55 -4
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/r-interoperability.md +14 -4
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/sensitivity-analysis.md +14 -6
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/zero-events.md +13 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/limitations.md +8 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/methods/statistical-methods.md +74 -17
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/reference/api.md +32 -12
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/reference/report-schema.md +2 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/reference/results.md +46 -7
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/releasing.md +5 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/validation.md +45 -17
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/mkdocs.yml +1 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/pyproject.toml +1 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/__init__.py +2 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/_version.py +1 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/api.py +65 -17
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/binary_api.py +30 -12
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/continuous_api.py +37 -16
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/data.py +40 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/design_matrix.py +80 -21
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/effect_sizes/binary.py +60 -19
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/effect_sizes/continuous.py +34 -4
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/estimators/inverse_variance.py +22 -6
- pymetaanalysis-0.5.0/src/meta_analyze/estimators/mantel_haenszel.py +140 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/estimators/meta_regression.py +117 -34
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/estimators/tau2.py +42 -20
- pymetaanalysis-0.5.0/src/meta_analyze/heterogeneity.py +285 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/_utils.py +10 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/forest.py +24 -5
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/subgroup_forest.py +32 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/regression_api.py +19 -6
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/regression_collinearity.py +3 -22
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/regression_results.py +48 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/regression_sensitivity.py +14 -38
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/reporting.py +28 -16
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/results.py +170 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/sensitivity.py +115 -33
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/subgroups.py +61 -12
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/README.md +23 -9
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/binary_metafor.json +12 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_binary_metafor.R +17 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_generic_metafor.R +32 -8
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_meta_regression_influence_metafor.R +22 -8
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_meta_regression_metafor.R +83 -2
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_workflow_metafor.R +10 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generic_metafor.json +27 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_influence_metafor.json +327 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_metafor.json +205 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/workflow_metafor.json +6 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_api.py +236 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_binary.py +92 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_continuous.py +41 -0
- pymetaanalysis-0.5.0/tests/test_estimators.py +350 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_funnel_plot.py +1 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_meta_regression.py +79 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_numerical_stability.py +128 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_plotting.py +11 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_properties.py +41 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_r_references.py +183 -5
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_regression_influence.py +65 -22
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_regression_plotting.py +1 -1
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_regression_sensitivity.py +25 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_release_readiness.py +39 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_reporting.py +5 -4
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_sensitivity.py +84 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_subgroups.py +102 -8
- pymetaanalysis-0.4.0/src/meta_analyze/estimators/mantel_haenszel.py +0 -101
- pymetaanalysis-0.4.0/src/meta_analyze/heterogeneity.py +0 -99
- pymetaanalysis-0.4.0/tests/test_estimators.py +0 -147
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/.gitignore +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/CONTRIBUTING.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/LICENSE +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/SECURITY.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/benchmarks/README.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/benchmarks/benchmark_core.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/adr/0001-optional-matplotlib.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/adr/0003-meta-regression-prediction-intervals.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/citation.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/development.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/getting-started.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/binary-outcomes.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/continuous-outcomes.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/generic-effects.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/plotting.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/guides/provenance-reporting.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/index.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/installation.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/docs/stylesheets/extra.css +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/examples/README.md +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/examples/meta_regression.ipynb +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/examples/quickstart.ipynb +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/config.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/effect_sizes/__init__.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/estimators/__init__.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/exceptions.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/__init__.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/funnel.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/plotting/regression.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/provenance.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/py.typed +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/src/meta_analyze/regression_contrasts.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/binary_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/binary_sparse_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/continuous_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/continuous_metafor.json +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_continuous_metafor.R +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_meta_regression_collinearity_metafor.R +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generate_meta_regression_contrasts_metafor.R +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/generic_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_boundary_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_collinearity_metafor.json +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_contrasts_metafor.json +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/meta_regression_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/reference/workflow_input.csv +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_documentation.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_reference_results.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_regression_collinearity.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tests/test_regression_contrasts.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tools/check_release.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tools/execute_notebooks.py +0 -0
- {pymetaanalysis-0.4.0 → pymetaanalysis-0.5.0}/tools/inspect_distribution.py +0 -0
|
@@ -8,7 +8,7 @@ on:
|
|
|
8
8
|
|
|
9
9
|
concurrency:
|
|
10
10
|
group: pages
|
|
11
|
-
cancel-in-progress:
|
|
11
|
+
cancel-in-progress: false
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
build:
|
|
@@ -17,7 +17,6 @@ jobs:
|
|
|
17
17
|
timeout-minutes: 10
|
|
18
18
|
permissions:
|
|
19
19
|
contents: read
|
|
20
|
-
pages: write
|
|
21
20
|
|
|
22
21
|
steps:
|
|
23
22
|
- name: Check out repository
|
|
@@ -35,14 +35,17 @@ jobs:
|
|
|
35
35
|
cache: pip
|
|
36
36
|
cache-dependency-path: pyproject.toml
|
|
37
37
|
|
|
38
|
-
- name: Install
|
|
38
|
+
- name: Install release dependencies
|
|
39
39
|
run: |
|
|
40
40
|
python -m pip install --upgrade pip
|
|
41
|
-
python -m pip install build twine
|
|
41
|
+
python -m pip install ".[test]" build twine
|
|
42
42
|
|
|
43
43
|
- name: Validate release metadata
|
|
44
44
|
run: python tools/check_release.py --tag "$GITHUB_REF_NAME"
|
|
45
45
|
|
|
46
|
+
- name: Run tests with branch coverage
|
|
47
|
+
run: python -m pytest --cov=meta_analyze --cov-branch --cov-report=term-missing
|
|
48
|
+
|
|
46
49
|
- name: Build distributions
|
|
47
50
|
run: python -m build
|
|
48
51
|
|
|
@@ -91,7 +94,8 @@ jobs:
|
|
|
91
94
|
path: dist/
|
|
92
95
|
|
|
93
96
|
- name: Publish to PyPI
|
|
94
|
-
|
|
97
|
+
# release/v1.14, pinned because this step holds the PyPI OIDC permission.
|
|
98
|
+
uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247
|
|
95
99
|
|
|
96
100
|
github-release:
|
|
97
101
|
name: Create GitHub Release
|
|
@@ -6,6 +6,85 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.5.0 - 2026-07-25
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- random-effects inverse-variance results now provide opt-in Q-profile
|
|
14
|
+
confidence intervals for tau-squared, tau, I-squared, and H-squared, with an
|
|
15
|
+
explicit formal-empty-set flag at the constrained `[0, 0]` boundary.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- sensitivity and influence workflows now borrow internal fitted buffers during
|
|
20
|
+
refits instead of repeatedly materializing public defensive copies;
|
|
21
|
+
- Meta-regression stores its classic coefficient covariance alongside the
|
|
22
|
+
selected inference covariance and reuses one shared precision-geometry
|
|
23
|
+
implementation across fitting and diagnostics.
|
|
24
|
+
- independent `metafor` fixtures now cover categorical and multivariable
|
|
25
|
+
influence diagnostics, no-intercept Riley prediction intervals, and explicit
|
|
26
|
+
Mantel-Haenszel pooling correction; iterative failure paths have direct
|
|
27
|
+
regression tests.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- inverse-variance means, heterogeneity statistics, and pooling and
|
|
32
|
+
meta-regression tau-squared equations now use overflow-safe relative-weight
|
|
33
|
+
calculations at the supported float64 boundary;
|
|
34
|
+
- subnormal variances and non-finite derived effects now raise explicit domain
|
|
35
|
+
errors instead of leaking runtime warnings or returning invalid results;
|
|
36
|
+
- binary OR, RD, and Mantel-Haenszel arithmetic now avoids intermediate
|
|
37
|
+
overflow for very large finite counts;
|
|
38
|
+
- the sensitivity guide no longer incorrectly states that Meta-regression
|
|
39
|
+
Cook's distance and DFBETAS are unavailable.
|
|
40
|
+
- subgroup-differences tests now use classic model variances independently of
|
|
41
|
+
Hartung-Knapp confidence-interval adjustments;
|
|
42
|
+
- leave-one-out and cumulative workflows now retain or skip, respectively,
|
|
43
|
+
reduced Mantel-Haenszel fits that are not estimable instead of aborting the
|
|
44
|
+
complete sensitivity analysis;
|
|
45
|
+
- forest and subgroup-forest plots now reject non-positive displayed
|
|
46
|
+
coordinates before enabling a logarithmic axis;
|
|
47
|
+
- uncorrected risk-ratio analyses now accept a zero non-event cell when the
|
|
48
|
+
study effect and sampling variance remain well defined.
|
|
49
|
+
- Hartung-Knapp random-effects prediction intervals now use the selected
|
|
50
|
+
adjusted pooled-mean variance and are recorded as `HK-PR`, matching
|
|
51
|
+
`metafor` Riley predictions;
|
|
52
|
+
- random-effects subgroup analyses now retain single-study subgroups through
|
|
53
|
+
an explicit, warned common-effect fallback instead of failing the complete
|
|
54
|
+
analysis;
|
|
55
|
+
- tagged releases now rerun the full branch-coverage test suite before
|
|
56
|
+
distributions can be built and published.
|
|
57
|
+
- tau-squared methods and SMD variance conventions now use `None` as the
|
|
58
|
+
context-sensitive default, so explicitly inapplicable settings raise domain
|
|
59
|
+
errors instead of being silently ignored;
|
|
60
|
+
- duplicate study labels now add a row-position warning while preserving
|
|
61
|
+
`row_id` as the unique audit key;
|
|
62
|
+
- report JSON now serializes `pd.NaT` study labels as `null` rather than the
|
|
63
|
+
string `"NaT"`.
|
|
64
|
+
- Meta-regression with `missing="drop"` now determines complete-row exclusions
|
|
65
|
+
before validating moderator values, so invalid values in already excluded
|
|
66
|
+
rows cannot abort the analysis;
|
|
67
|
+
- cumulative analysis now rejects ambiguous string `order` selectors that
|
|
68
|
+
exist in both source data and study results;
|
|
69
|
+
- empty inputs now report that at least one study row is required, and binary
|
|
70
|
+
zero-cell errors identify when `correction_scope="none"` disables an
|
|
71
|
+
otherwise positive correction.
|
|
72
|
+
- iterative tau-squared estimators now mark only an exact constrained zero as
|
|
73
|
+
a boundary solution, rather than treating every positive root below `atol`
|
|
74
|
+
as zero;
|
|
75
|
+
- the exported pooling and Meta-regression tau-squared estimators now reject
|
|
76
|
+
insufficient study or residual degrees of freedom with domain-specific
|
|
77
|
+
errors;
|
|
78
|
+
- the Mantel-Haenszel estimator now rejects empty and zero-total strata before
|
|
79
|
+
division, preventing NaN propagation and misleading variance diagnostics.
|
|
80
|
+
- prediction-interval metadata is now `None` when too few studies prevent an
|
|
81
|
+
interval from being calculated;
|
|
82
|
+
- categorical moderator encoding no longer conflates booleans, integers, and
|
|
83
|
+
floating-point values through Python's cross-type numeric equality;
|
|
84
|
+
- CI now covers Python 3.14, Pages deployments are not cancelled mid-flight,
|
|
85
|
+
and the credential-bearing PyPI publisher action is pinned to an immutable
|
|
86
|
+
commit.
|
|
87
|
+
|
|
9
88
|
## 0.4.0 - 2026-07-23
|
|
10
89
|
|
|
11
90
|
### 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.5.0
|
|
12
|
+
date-released: 2026-07-25
|
|
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.5.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
|
|
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
22
|
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
22
23
|
Requires-Python: >=3.10
|
|
23
24
|
Requires-Dist: numpy>=1.24
|
|
@@ -139,7 +140,10 @@ not individual-level or causal effects.
|
|
|
139
140
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
140
141
|
and DerSimonian-Laird tau-squared estimators. Mean confidence intervals support
|
|
141
142
|
the normal default plus unmodified and safeguarded Hartung-Knapp variants.
|
|
142
|
-
Eligible random-effects fits include an HTS prediction interval
|
|
143
|
+
Eligible random-effects fits include an HTS prediction interval under normal
|
|
144
|
+
inference and an HK-PR interval under either Hartung-Knapp variant. Call
|
|
145
|
+
`result.tau2_confidence_interval()` for a Q-profile interval around
|
|
146
|
+
heterogeneity.
|
|
143
147
|
|
|
144
148
|
Generic analyses accept exactly one of `variance=` or `standard_error=`.
|
|
145
149
|
Standard errors are squared internally and the conversion is recorded in the
|
|
@@ -157,6 +161,7 @@ result.estimate
|
|
|
157
161
|
result.display_estimate
|
|
158
162
|
result.ci
|
|
159
163
|
result.tau2
|
|
164
|
+
tau2_interval = result.tau2_confidence_interval()
|
|
160
165
|
result.i2
|
|
161
166
|
result.i2_method
|
|
162
167
|
result.diagnostics
|
|
@@ -90,7 +90,10 @@ not individual-level or causal effects.
|
|
|
90
90
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
91
91
|
and DerSimonian-Laird tau-squared estimators. Mean confidence intervals support
|
|
92
92
|
the normal default plus unmodified and safeguarded Hartung-Knapp variants.
|
|
93
|
-
Eligible random-effects fits include an HTS prediction interval
|
|
93
|
+
Eligible random-effects fits include an HTS prediction interval under normal
|
|
94
|
+
inference and an HK-PR interval under either Hartung-Knapp variant. Call
|
|
95
|
+
`result.tau2_confidence_interval()` for a Q-profile interval around
|
|
96
|
+
heterogeneity.
|
|
94
97
|
|
|
95
98
|
Generic analyses accept exactly one of `variance=` or `standard_error=`.
|
|
96
99
|
Standard errors are squared internally and the conversion is recorded in the
|
|
@@ -108,6 +111,7 @@ result.estimate
|
|
|
108
111
|
result.display_estimate
|
|
109
112
|
result.ci
|
|
110
113
|
result.tau2
|
|
114
|
+
tau2_interval = result.tau2_confidence_interval()
|
|
111
115
|
result.i2
|
|
112
116
|
result.i2_method
|
|
113
117
|
result.diagnostics
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
- Status: Accepted
|
|
4
4
|
- Date: 2026-07-15
|
|
5
|
+
- Amendment: the prediction-interval variance decision is superseded by
|
|
6
|
+
[ADR 0004](0004-hartung-knapp-prediction-intervals.md).
|
|
5
7
|
|
|
6
8
|
## Context
|
|
7
9
|
|
|
@@ -65,10 +67,11 @@ percentage in human-readable output.
|
|
|
65
67
|
|
|
66
68
|
### Prediction intervals
|
|
67
69
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
The original decision used the Higgins-Thompson-Spiegelhalter prediction
|
|
71
|
+
interval with `k - 2` degrees of freedom and the classic variance of the
|
|
72
|
+
pooled mean for every confidence-interval method. ADR 0004 replaces that
|
|
73
|
+
variance rule for Hartung-Knapp fits while retaining the study-count boundary
|
|
74
|
+
and small-sample warning.
|
|
72
75
|
|
|
73
76
|
## Validation
|
|
74
77
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# ADR 0004: Hartung-Knapp prediction intervals
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-07-24
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
ADR 0002 applied the classic pooled-mean variance to every `k - 2`
|
|
9
|
+
random-effects prediction interval. That kept the interval independent of
|
|
10
|
+
`ci_method`, but it diverged from `metafor` Riley predictions and the
|
|
11
|
+
Hartung-Knapp Partlett-Riley option in R `meta`. Both use the covariance
|
|
12
|
+
selected for mean inference inside the prediction variance.
|
|
13
|
+
|
|
14
|
+
This difference was material when the unmodified Hartung-Knapp variance was
|
|
15
|
+
below or above the classic variance. The result metadata still identified the
|
|
16
|
+
interval as `HTS`, so callers could not discover the difference from method
|
|
17
|
+
configuration alone.
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
Random-effects inverse-variance prediction intervals retain the `k - 2`
|
|
22
|
+
critical value and three-study minimum:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
mu_hat +/- t_(k - 2, 1 - alpha/2)
|
|
26
|
+
* sqrt(tau^2 + Var_selected(mu_hat))
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- normal inference uses the classic pooled-mean variance and records `HTS`;
|
|
30
|
+
- `hartung_knapp` uses its unmodified adjusted variance and records `HK-PR`;
|
|
31
|
+
- `hartung_knapp_adhoc` uses its lower-bounded adjusted variance and records
|
|
32
|
+
`HK-PR`.
|
|
33
|
+
|
|
34
|
+
Committed values are generated directly from
|
|
35
|
+
`metafor::predict(fit, predtype="Riley")` for all three inference choices.
|
|
36
|
+
Prediction intervals remain unavailable below three included studies and
|
|
37
|
+
retain the explicit warning with three or four studies.
|
|
38
|
+
|
|
39
|
+
## Consequences
|
|
40
|
+
|
|
41
|
+
- prediction intervals and mean intervals use a coherent selected covariance;
|
|
42
|
+
- HK and safeguarded HK prediction intervals can differ from the normal HTS
|
|
43
|
+
interval even when tau-squared and the pooled estimate are unchanged;
|
|
44
|
+
- `result.method.prediction_interval_method` distinguishes `HTS` from
|
|
45
|
+
`HK-PR`;
|
|
46
|
+
- this decision supersedes only the prediction-variance paragraph of ADR 0002.
|
|
@@ -54,7 +54,10 @@ zero.
|
|
|
54
54
|
`row_id` is the zero-based input position. It is independent of the study
|
|
55
55
|
label and remains stable through exclusion, subgroup, leave-one-out, and
|
|
56
56
|
cumulative workflows. Use it when study labels are duplicated or not suitable
|
|
57
|
-
as identifiers.
|
|
57
|
+
as identifiers. Duplicate labels are accepted because several rows can
|
|
58
|
+
legitimately originate from the same publication, but the result records the
|
|
59
|
+
affected row positions in `warnings` so accidental duplication remains
|
|
60
|
+
auditable.
|
|
58
61
|
|
|
59
62
|
The complete row table is available from:
|
|
60
63
|
|
|
@@ -84,6 +87,13 @@ result = ma.meta_analysis(
|
|
|
84
87
|
result.excluded_studies[["row_id", "study", "exclusion_reason"]]
|
|
85
88
|
```
|
|
86
89
|
|
|
90
|
+
For Meta-regression, missingness is resolved across the outcome, uncertainty,
|
|
91
|
+
study label, and every moderator before moderator values are validated.
|
|
92
|
+
Consequently, a moderator value in an already excluded row is retained for
|
|
93
|
+
audit but cannot abort or influence the fitted design matrix. Moderator values
|
|
94
|
+
in included rows must still satisfy the declared numeric or categorical
|
|
95
|
+
contract.
|
|
96
|
+
|
|
87
97
|
Dropped rows do not contribute to pooled estimates, Q, tau-squared, prediction
|
|
88
98
|
intervals, or weights. Missing subgroup labels are always rejected because
|
|
89
99
|
silently assigning or dropping them would change the subgroup definition.
|
|
@@ -92,7 +102,7 @@ silently assigning or dropping them would change the subgroup definition.
|
|
|
92
102
|
|
|
93
103
|
| Input family | Required validation |
|
|
94
104
|
| --- | --- |
|
|
95
|
-
| Generic | finite effect; finite, strictly positive sampling variance |
|
|
105
|
+
| Generic | finite effect; finite, strictly positive sampling variance large enough for a finite float64 inverse weight |
|
|
96
106
|
| Binary | integer event counts and totals; positive totals; `0 <= events <= total` |
|
|
97
107
|
| Continuous | finite means/SDs; non-negative SDs; integer group sizes of at least 2 |
|
|
98
108
|
|
|
@@ -100,6 +110,12 @@ Binary and continuous APIs preserve their raw input columns in
|
|
|
100
110
|
`study_results`. Derived effects, variances, correction indicators, and
|
|
101
111
|
weights appear alongside them.
|
|
102
112
|
|
|
113
|
+
All numerical calculations use float64. Internally derived effects and
|
|
114
|
+
variances must remain finite, and every included sampling variance must be
|
|
115
|
+
large enough to produce a finite inverse-variance weight. Values outside that
|
|
116
|
+
representable range raise `InvalidStudyDataError` instead of returning
|
|
117
|
+
non-finite fitted results.
|
|
118
|
+
|
|
103
119
|
## Exclusion is visible
|
|
104
120
|
|
|
105
121
|
Rows excluded by a configured rule remain present with:
|
|
@@ -67,6 +67,10 @@ This produces terms such as `region[Asia]` and `region[North America]`, each
|
|
|
67
67
|
relative to `Europe`. The reference never depends on row order. Undeclared
|
|
68
68
|
levels, levels absent after exclusions, and string moderators omitted from
|
|
69
69
|
`categorical=` are errors rather than implicit recoding decisions.
|
|
70
|
+
Categorical matching preserves scalar kinds: Python and NumPy integers are
|
|
71
|
+
equivalent, for example, but booleans do not match integer levels and
|
|
72
|
+
floating-point values do not match integer levels. Declare levels using the
|
|
73
|
+
same scalar kind as the observed moderator values.
|
|
70
74
|
|
|
71
75
|
Formula parsing, automatic interactions, splines, and polynomial terms are not
|
|
72
76
|
implemented. Construct those columns explicitly before fitting when they are
|
|
@@ -17,6 +17,20 @@ variation is part of the estimand. A small number of studies makes
|
|
|
17
17
|
between-study variance and interval estimation uncertain; it does not turn a
|
|
18
18
|
random-effects question into a common-effect question.
|
|
19
19
|
|
|
20
|
+
The high-level APIs intentionally have outcome-specific defaults:
|
|
21
|
+
|
|
22
|
+
| API | Default model and pooling |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `meta_analysis()` | random-effects inverse variance, REML |
|
|
25
|
+
| `meta_continuous()` | random-effects inverse variance, REML |
|
|
26
|
+
| `meta_binary()` | common-effect Mantel-Haenszel |
|
|
27
|
+
| `meta_regression()` | mixed-effects inverse variance, REML |
|
|
28
|
+
|
|
29
|
+
These defaults reflect common entry-point conventions, not an automatic model
|
|
30
|
+
choice. Switching outcome APIs can therefore switch the model family; set
|
|
31
|
+
`model` and, for binary data, `method` explicitly in analysis code and
|
|
32
|
+
protocols.
|
|
33
|
+
|
|
20
34
|
## Pooling methods
|
|
21
35
|
|
|
22
36
|
| Data and model | Available pooling method |
|
|
@@ -42,9 +56,17 @@ Random-effects inverse-variance models provide:
|
|
|
42
56
|
|
|
43
57
|
REML and PM are iterative. Convergence, iteration count, and whether the
|
|
44
58
|
solution reached the zero boundary are recorded in `result.diagnostics`.
|
|
59
|
+
The boundary flag means the constrained estimate is exactly zero; a positive
|
|
60
|
+
root remains a positive estimate even when it is smaller than the configured
|
|
61
|
+
root-finding tolerance.
|
|
45
62
|
Failure to converge raises `ConvergenceError`; it does not silently fall back
|
|
46
63
|
to DL.
|
|
47
64
|
|
|
65
|
+
The public default is `tau2_method=None`: it resolves to REML for a random- or
|
|
66
|
+
mixed-effects fit. Common-effect and Mantel-Haenszel fits reject an explicitly
|
|
67
|
+
supplied tau-squared method so analysis code cannot appear to request an
|
|
68
|
+
estimator that was not used.
|
|
69
|
+
|
|
48
70
|
## Confidence intervals
|
|
49
71
|
|
|
50
72
|
`ci_method="normal"` is the stable default and uses the classic normal
|
|
@@ -85,12 +107,36 @@ The definition is recorded as `result.i2_method`: `q_based` or
|
|
|
85
107
|
`tau2_typical_variance`. Internally, I-squared remains a proportion from zero
|
|
86
108
|
to one.
|
|
87
109
|
|
|
110
|
+
## Heterogeneity confidence intervals
|
|
111
|
+
|
|
112
|
+
A random-effects inverse-variance fit can invert generalized Q to quantify
|
|
113
|
+
uncertainty around tau-squared:
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
heterogeneity_interval = result.tau2_confidence_interval()
|
|
117
|
+
heterogeneity_interval.ci
|
|
118
|
+
heterogeneity_interval.i2_ci
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The point estimate still follows the selected DL, PM, or REML estimator. The
|
|
122
|
+
Q-profile interval is a separate procedure and therefore is identical across
|
|
123
|
+
those point estimators for the same data and confidence level; it is not
|
|
124
|
+
guaranteed to contain every possible point estimate.
|
|
125
|
+
|
|
126
|
+
For unusually homogeneous data, both unconstrained bounds can lie below zero.
|
|
127
|
+
The method then has a formal empty confidence set. PyMetaAnalysis exposes
|
|
128
|
+
`is_empty=True` while representing the constrained tau-squared display as
|
|
129
|
+
`[0, 0]`; do not interpret that display as proof that heterogeneity is exactly
|
|
130
|
+
zero.
|
|
131
|
+
|
|
88
132
|
## Prediction intervals
|
|
89
133
|
|
|
90
|
-
Random-effects models report
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
134
|
+
Random-effects models report a prediction interval when at least three studies
|
|
135
|
+
are included. Under normal inference this is recorded as `HTS`; either
|
|
136
|
+
Hartung-Knapp choice supplies its selected pooled-mean variance and is recorded
|
|
137
|
+
as `HK-PR`. It describes uncertainty for a new study's underlying effect, not
|
|
138
|
+
uncertainty around the pooled mean. Common-effect models do not produce
|
|
139
|
+
prediction intervals. With three or four studies the interval is still
|
|
94
140
|
calculated, but the result warns that it is especially uncertain.
|
|
95
141
|
|
|
96
142
|
## Subgroups
|
|
@@ -101,6 +147,11 @@ within each subgroup and again for the overall model. This is recorded as
|
|
|
101
147
|
differences compares subgroup summary estimates; it is not a comparison of
|
|
102
148
|
whether individual subgroup p-values are significant.
|
|
103
149
|
|
|
150
|
+
If a subgroup contains only one included study, tau-squared and random-effects
|
|
151
|
+
inference are not estimable within that subgroup. PyMetaAnalysis retains it as
|
|
152
|
+
the study's common-effect estimate and normal interval, records the fallback
|
|
153
|
+
in warnings, and continues the overall random-effects subgroup analysis.
|
|
154
|
+
|
|
104
155
|
## Reporting checklist
|
|
105
156
|
|
|
106
157
|
At minimum, report:
|
|
@@ -69,7 +69,7 @@ remain explicit attributes in Python.
|
|
|
69
69
|
| `model="random"` | random-effects `rma.uni()` | `random=TRUE` | Requires a tau-squared policy |
|
|
70
70
|
| `method="IV"` | inverse-variance weighting | `method="Inverse"` | Binary API only; generic and continuous fits are IV |
|
|
71
71
|
| `method="MH"` | `rma.mh()` | `method="MH"` | Common-effect OR/RR only |
|
|
72
|
-
| `tau2_method="REML"` | `method="REML"` | `method.tau="REML"` | PyMetaAnalysis random-effects default |
|
|
72
|
+
| `tau2_method=None` (resolved as `"REML"`) | `method="REML"` | `method.tau="REML"` | PyMetaAnalysis random-effects default |
|
|
73
73
|
| `tau2_method="PM"` | `method="PM"` | `method.tau="PM"` | Paule-Mandel |
|
|
74
74
|
| `tau2_method="DL"` | `method="DL"` | `method.tau="DL"` | DerSimonian-Laird |
|
|
75
75
|
|
|
@@ -79,6 +79,13 @@ handling, or heterogeneity definitions. In particular, PyMetaAnalysis records
|
|
|
79
79
|
tau-squared/typical-variance definition, while common-effect and MH results use
|
|
80
80
|
the Q-based definition.
|
|
81
81
|
|
|
82
|
+
`result.tau2_confidence_interval()` corresponds to
|
|
83
|
+
`confint(fit, type="QP")` for an `rma.uni` random-effects fit. Both return
|
|
84
|
+
Q-profile bounds for tau-squared and monotonic tau, I-squared, and H-squared
|
|
85
|
+
transformations. PyMetaAnalysis additionally exposes `is_empty` so a formal
|
|
86
|
+
empty confidence set is distinguishable from its constrained `[0, 0]`
|
|
87
|
+
display.
|
|
88
|
+
|
|
82
89
|
## Confidence and prediction intervals
|
|
83
90
|
|
|
84
91
|
| PyMetaAnalysis `ci_method` | `metafor` | R `meta` | Behavior |
|
|
@@ -87,9 +94,12 @@ the Q-based definition.
|
|
|
87
94
|
| `"hartung_knapp"` | `test="knha"` | `method.random.ci="HK"` | Unmodified HK variance and t quantile |
|
|
88
95
|
| `"hartung_knapp_adhoc"` | `test="adhoc"` | HK plus an explicitly selected ad hoc correction | HK variance cannot fall below the classic variance |
|
|
89
96
|
|
|
90
|
-
Eligible random-effects fits
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
Eligible random-effects fits use the documented HTS prediction interval under
|
|
98
|
+
normal inference. Either Hartung-Knapp choice instead uses its selected
|
|
99
|
+
pooled-mean variance with `k-2` degrees of freedom (`HK-PR`), matching
|
|
100
|
+
`predict(fit, predtype="Riley")` in `metafor`. R packages offer additional
|
|
101
|
+
prediction-interval choices, so method settings must still be compared
|
|
102
|
+
explicitly.
|
|
93
103
|
|
|
94
104
|
Meta-regression uses a separate prediction rule. Its default corresponds to
|
|
95
105
|
`predict(fit)` in `metafor`: normal inference uses a normal critical value and
|
|
@@ -18,13 +18,17 @@ print(influence.to_dataframe())
|
|
|
18
18
|
The returned `LeaveOneOutResult` contains:
|
|
19
19
|
|
|
20
20
|
- `original`, the fitted result supplied to the workflow;
|
|
21
|
-
- `results`, one immutable refit per
|
|
21
|
+
- `results`, one omission-aligned immutable refit or `None` per included study;
|
|
22
22
|
- `table`, `summary()`, and `to_dataframe()`, which return defensive copies;
|
|
23
|
+
- `failed`, the rows for reduced models that could not be estimated;
|
|
23
24
|
- `warnings`, for workflow-level notes.
|
|
24
25
|
|
|
25
26
|
The table identifies `omitted_row_id` and `omitted_study` and reports each
|
|
26
27
|
refit's estimate, standard error, confidence interval, tau-squared, Q,
|
|
27
|
-
I-squared, and H-squared.
|
|
28
|
+
I-squared, and H-squared. It also records `refit_success`, `error_type`, and
|
|
29
|
+
`error_message`. An unestimable deletion remains aligned in `results` as
|
|
30
|
+
`None`, retains a table row with unavailable numeric values, and does not stop
|
|
31
|
+
the remaining deletions.
|
|
28
32
|
|
|
29
33
|
Originally excluded rows are never omission candidates. Common-effect analysis
|
|
30
34
|
requires at least two included studies so each refit retains one. Random-effects
|
|
@@ -125,9 +129,17 @@ cumulative = result.cumulative(
|
|
|
125
129
|
)
|
|
126
130
|
```
|
|
127
131
|
|
|
132
|
+
A string selector must identify exactly one namespace. If the same column name
|
|
133
|
+
exists in both the original source data and the result study table, it is
|
|
134
|
+
ambiguous and raises `InvalidStudyDataError`. Pass the intended Series or array
|
|
135
|
+
explicitly, for example `order=studies["publication_year"]`.
|
|
136
|
+
|
|
128
137
|
`CumulativeMetaAnalysisResult.results` contains the estimable prefix fits, and
|
|
129
138
|
`final` returns the last fit. Its table records the rows and study labels added
|
|
130
139
|
at each step together with the same principal statistics as leave-one-out.
|
|
140
|
+
If an otherwise eligible prefix is not estimable, it is skipped with an
|
|
141
|
+
explicit warning. Its pending studies are included in the next estimable
|
|
142
|
+
prefix row, so the cumulative path and final all-study fit remain complete.
|
|
131
143
|
|
|
132
144
|
When multiple studies have the same order value, `collapse=True` adds the tied
|
|
133
145
|
studies in one step:
|
|
@@ -184,7 +196,3 @@ design, outcome definition, risk of bias, and numerical leverage. They are not
|
|
|
184
196
|
by themselves a reason to exclude the study. Likewise, a cumulative trend can
|
|
185
197
|
describe the historical evidence path but does not remove time-related changes
|
|
186
198
|
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.
|
|
@@ -28,6 +28,11 @@ Available scopes are:
|
|
|
28
28
|
Setting the correction to zero or the scope to `none` is rejected when it
|
|
29
29
|
leaves an OR/RR undefined or an effect variance non-positive.
|
|
30
30
|
|
|
31
|
+
For RR, a zero non-event cell is allowed when both arms still have positive
|
|
32
|
+
event counts and the sampling variance is positive. For example, a study with
|
|
33
|
+
events in every participant of one arm can be analyzed without correction.
|
|
34
|
+
OR still requires all four cells to be positive.
|
|
35
|
+
|
|
31
36
|
## Double-zero and double-all studies
|
|
32
37
|
|
|
33
38
|
A study with no events in either group, or events in every participant in both
|
|
@@ -47,8 +52,14 @@ rd_zero_variance = "correct"
|
|
|
47
52
|
```
|
|
48
53
|
|
|
49
54
|
The RD itself remains the raw treatment risk minus control risk. Corrected
|
|
50
|
-
counts
|
|
51
|
-
|
|
55
|
+
counts affect only its sampling variance. Under the default
|
|
56
|
+
`correction_scope="only_zero_studies"`, the corrected variance is used for
|
|
57
|
+
every retained RD table containing at least one zero cell, including
|
|
58
|
+
single-zero tables whose uncorrected variance was already positive. The
|
|
59
|
+
`rd_zero_variance` policy separately decides whether tables whose raw RD
|
|
60
|
+
variance is exactly zero are retained or excluded. To exclude all such
|
|
61
|
+
zero-variance studies before pooling, Q, tau-squared, and weight calculations,
|
|
62
|
+
use:
|
|
52
63
|
|
|
53
64
|
```python
|
|
54
65
|
rd_zero_variance = "exclude"
|
|
@@ -12,9 +12,14 @@ deferred functionality explicit.
|
|
|
12
12
|
- common-effect and univariate random-effects inverse-variance models;
|
|
13
13
|
- common-effect Mantel-Haenszel OR/RR;
|
|
14
14
|
- DL, PM, and REML tau-squared estimators;
|
|
15
|
+
- Q-profile confidence intervals for tau-squared and its monotonic tau,
|
|
16
|
+
I-squared, and H-squared transformations in random-effects inverse-variance
|
|
17
|
+
models;
|
|
15
18
|
- normal and random-effects Hartung-Knapp mean intervals;
|
|
16
|
-
- HTS prediction intervals;
|
|
17
|
-
- independent subgroup fits and a formal subgroup-differences test
|
|
19
|
+
- HTS and Hartung-Knapp Partlett-Riley (`HK-PR`) prediction intervals;
|
|
20
|
+
- independent subgroup fits and a formal subgroup-differences test, with a
|
|
21
|
+
warned common-effect representation when a random-effects subgroup contains
|
|
22
|
+
only one included study;
|
|
18
23
|
- leave-one-out and cumulative repeated-fit workflows;
|
|
19
24
|
- forest and descriptive funnel plots;
|
|
20
25
|
- structured provenance and reports;
|
|
@@ -32,6 +37,7 @@ deferred functionality explicit.
|
|
|
32
37
|
- Mantel-Haenszel risk differences or random-effects MH pooling;
|
|
33
38
|
- formula parsing, automatic interactions/splines, stepwise moderator
|
|
34
39
|
selection, automatic pairwise contrasts, or multiplicity correction;
|
|
40
|
+
- Q-profile confidence intervals for residual tau-squared in Meta-regression;
|
|
35
41
|
- multilevel, multivariate, network, dose-response, diagnostic-accuracy, or
|
|
36
42
|
individual-participant-data meta-analysis;
|
|
37
43
|
- robust variance estimation or dependent-effect clustering;
|