PyMetaAnalysis 0.5.0__tar.gz → 0.7.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.5.0 → pymetaanalysis-0.7.0}/.gitignore +1 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CHANGELOG.md +63 -7
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CITATION.cff +2 -2
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/PKG-INFO +13 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/README.md +12 -4
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/benchmarks/README.md +5 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/benchmarks/benchmark_core.py +8 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0002-statistical-policy.md +8 -2
- pymetaanalysis-0.7.0/docs/adr/0005-mantel-haenszel-risk-difference.md +65 -0
- pymetaanalysis-0.7.0/docs/adr/0006-peto-odds-ratio.md +87 -0
- pymetaanalysis-0.7.0/docs/adr/0007-fisher-z-correlation.md +66 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/citation.md +1 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/development.md +2 -2
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/getting-started.md +5 -3
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/binary-outcomes.md +33 -5
- pymetaanalysis-0.7.0/docs/guides/correlation-outcomes.md +150 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/input-data.md +3 -2
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/meta-regression.md +5 -4
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/method-selection.md +20 -11
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/plotting.md +3 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/provenance-reporting.md +12 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/r-interoperability.md +31 -6
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/sensitivity-analysis.md +3 -3
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/zero-events.md +45 -10
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/index.md +9 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/installation.md +1 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/limitations.md +19 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/methods/statistical-methods.md +106 -9
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/api.md +69 -13
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/report-schema.md +10 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/results.md +22 -6
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/releasing.md +16 -17
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/validation.md +13 -4
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/mkdocs.yml +4 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/pyproject.toml +2 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/__init__.py +2 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/_version.py +1 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/binary_api.py +122 -28
- pymetaanalysis-0.7.0/src/meta_analyze/correlation_api.py +317 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/design_matrix.py +22 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/__init__.py +8 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/binary.py +93 -0
- pymetaanalysis-0.7.0/src/meta_analyze/effect_sizes/correlation.py +215 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/__init__.py +3 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/mantel_haenszel.py +52 -7
- pymetaanalysis-0.7.0/src/meta_analyze/estimators/peto.py +159 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/heterogeneity.py +8 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/_utils.py +3 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/reporting.py +29 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/results.py +2 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/sensitivity.py +26 -4
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/subgroups.py +4 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/README.md +18 -1
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_metafor.json +60 -1
- pymetaanalysis-0.7.0/tests/reference/correlation_input.csv +9 -0
- pymetaanalysis-0.7.0/tests/reference/correlation_metafor.json +27 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_binary_metafor.R +80 -16
- pymetaanalysis-0.7.0/tests/reference/generate_correlation_metafor.R +59 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_generic_metafor.R +10 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_workflow_metafor.R +29 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generic_metafor.json +7 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/workflow_metafor.json +14 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_binary.py +324 -1
- pymetaanalysis-0.7.0/tests/test_correlation.py +288 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_estimators.py +62 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_funnel_plot.py +20 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_meta_regression.py +42 -13
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_plotting.py +24 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_properties.py +210 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_r_references.py +134 -10
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_release_readiness.py +1 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_reporting.py +42 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_sensitivity.py +48 -6
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_subgroups.py +33 -5
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/ci.yml +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/pages.yml +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/release.yml +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CONTRIBUTING.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/LICENSE +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/SECURITY.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0001-optional-matplotlib.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0003-meta-regression-prediction-intervals.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0004-hartung-knapp-prediction-intervals.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/continuous-outcomes.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/generic-effects.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/stylesheets/extra.css +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/README.md +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/meta_regression.ipynb +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/quickstart.ipynb +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/api.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/config.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/continuous_api.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/data.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/continuous.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/inverse_variance.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/meta_regression.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/tau2.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/exceptions.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/__init__.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/forest.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/funnel.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/regression.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/subgroup_forest.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/provenance.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/py.typed +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_api.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_collinearity.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_contrasts.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_results.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_sensitivity.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_sparse_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/continuous_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/continuous_metafor.json +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_continuous_metafor.R +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_collinearity_metafor.R +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_contrasts_metafor.R +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_influence_metafor.R +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_metafor.R +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generic_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_boundary_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_collinearity_metafor.json +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_contrasts_metafor.json +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_influence_metafor.json +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_metafor.json +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/workflow_input.csv +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_api.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_continuous.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_documentation.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_numerical_stability.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_reference_results.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_collinearity.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_contrasts.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_influence.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_plotting.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_sensitivity.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tools/check_release.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tools/execute_notebooks.py +0 -0
- {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tools/inspect_distribution.py +0 -0
|
@@ -6,6 +6,54 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 0.7.0 - 2026-09-02
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `meta_correlation()` for independent study-level correlations using Fisher's
|
|
14
|
+
r-to-z transformation (`ZCOR`), `1 / (n - 3)` sampling variances, common- or
|
|
15
|
+
REML/PM/DL random-effects inverse-variance pooling, back-transformed result
|
|
16
|
+
displays, subgroup and sensitivity workflows, plotting, provenance, reports,
|
|
17
|
+
and independent R `metafor` references.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- integer-valued floating-point categorical moderators now match declared
|
|
22
|
+
integer levels while booleans remain distinct, supporting pandas columns
|
|
23
|
+
promoted to floating point by missing values;
|
|
24
|
+
- MH pooling corrections now use `None` as the context-sensitive scope default;
|
|
25
|
+
explicitly supplying either MH-only option to IV or Peto pooling raises an
|
|
26
|
+
error, and non-MH method metadata no longer records unused MH settings;
|
|
27
|
+
- estimator documentation now makes the pooled-mean-only Q-profile contract,
|
|
28
|
+
the prefiltered `fit_peto()` input contract, and sparse MH RD boundary policy
|
|
29
|
+
explicit;
|
|
30
|
+
- fixed-version `metafor` references now cover a two-study Hartung-Knapp
|
|
31
|
+
interval and Q-profile intervals reached through random-effects subgroups.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- normal-inference subgroup tests reuse each fitted standard error directly,
|
|
36
|
+
avoiding an unnecessary recomputation and last-bit numerical drift.
|
|
37
|
+
- Peto observed-minus-expected arithmetic now uses a treatment/control-symmetric
|
|
38
|
+
formulation, preventing avoidable last-bit drift for highly imbalanced arms.
|
|
39
|
+
|
|
40
|
+
## 0.6.0 - 2026-08-13
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- common-effect Peto one-step odds-ratio pooling, including Peto-specific
|
|
45
|
+
study estimates, O-minus-E heterogeneity, explicit approximation warnings,
|
|
46
|
+
provenance/report metadata, and independent R `metafor` references;
|
|
47
|
+
- common-effect Mantel-Haenszel risk-difference pooling with the
|
|
48
|
+
Sato-Greenland-Robins sampling variance, explicit method metadata,
|
|
49
|
+
sparse-table policy integration, and independent R `metafor` references.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- isolated builds temporarily cap Hatchling below 1.32 so the release
|
|
54
|
+
workflow continues to produce Core Metadata 2.4 accepted by Twine 6.2;
|
|
55
|
+
the cap can be removed once Twine validates Metadata 2.5.
|
|
56
|
+
|
|
9
57
|
## 0.5.0 - 2026-07-25
|
|
10
58
|
|
|
11
59
|
### Added
|
|
@@ -26,6 +74,21 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
26
74
|
Mantel-Haenszel pooling correction; iterative failure paths have direct
|
|
27
75
|
regression tests.
|
|
28
76
|
|
|
77
|
+
### Breaking changes
|
|
78
|
+
|
|
79
|
+
- explicitly supplying `tau2_method` to a common-effect model, including the
|
|
80
|
+
former default spelling `"REML"`, now raises an error instead of being
|
|
81
|
+
ignored; explicitly inapplicable SMD variance settings follow the same rule;
|
|
82
|
+
- cumulative analysis now rejects a string `order` selector when the name is
|
|
83
|
+
present in both source data and the calculated study table, instead of
|
|
84
|
+
silently preferring the source-data column;
|
|
85
|
+
- `LeaveOneOutResult.results` now preserves failed refits as `None`, and its
|
|
86
|
+
table adds `refit_success`, `error_type`, and `error_message` columns;
|
|
87
|
+
- pooled-result `prediction_interval_method` metadata now uses `null` when an
|
|
88
|
+
interval is unavailable and `"HK-PR"` for Hartung-Knapp intervals. Report
|
|
89
|
+
schema 1.2 remains unchanged because the field itself was already present;
|
|
90
|
+
consumers must handle the documented value set.
|
|
91
|
+
|
|
29
92
|
### Fixed
|
|
30
93
|
|
|
31
94
|
- inverse-variance means, heterogeneity statistics, and pooling and
|
|
@@ -54,9 +117,6 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
54
117
|
analysis;
|
|
55
118
|
- tagged releases now rerun the full branch-coverage test suite before
|
|
56
119
|
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
120
|
- duplicate study labels now add a row-position warning while preserving
|
|
61
121
|
`row_id` as the unique audit key;
|
|
62
122
|
- report JSON now serializes `pd.NaT` study labels as `null` rather than the
|
|
@@ -64,8 +124,6 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
64
124
|
- Meta-regression with `missing="drop"` now determines complete-row exclusions
|
|
65
125
|
before validating moderator values, so invalid values in already excluded
|
|
66
126
|
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
127
|
- empty inputs now report that at least one study row is required, and binary
|
|
70
128
|
zero-cell errors identify when `correction_scope="none"` disables an
|
|
71
129
|
otherwise positive correction.
|
|
@@ -77,8 +135,6 @@ Changes planned for the next release accumulate under `Unreleased`.
|
|
|
77
135
|
errors;
|
|
78
136
|
- the Mantel-Haenszel estimator now rejects empty and zero-total strata before
|
|
79
137
|
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
138
|
- categorical moderator encoding no longer conflates booleans, integers, and
|
|
83
139
|
floating-point values through Python's cross-type numeric equality;
|
|
84
140
|
- CI now covers Python 3.14, Pages deployments are not cancelled mid-flight,
|
|
@@ -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-
|
|
11
|
+
version: 0.7.0
|
|
12
|
+
date-released: 2026-09-02
|
|
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.7.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
|
|
@@ -133,8 +133,9 @@ not individual-level or causal effects.
|
|
|
133
133
|
| Input | Effects | Pooling/models |
|
|
134
134
|
| --- | --- | --- |
|
|
135
135
|
| Effect + sampling variance or standard error | Generic | Common/random inverse variance |
|
|
136
|
-
| Two-group events + totals | OR, RR, RD | Common MH OR
|
|
136
|
+
| Two-group events + totals | OR, RR, RD | Common MH; common Peto OR; common/random IV |
|
|
137
137
|
| Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
|
|
138
|
+
| Correlations + sample sizes | Fisher's z (`ZCOR`) | Common/random inverse variance |
|
|
138
139
|
| Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
|
|
139
140
|
|
|
140
141
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
@@ -153,6 +154,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
|
|
|
153
154
|
corrections are separate, relative-effect double-zero/double-all rows remain
|
|
154
155
|
visible as exclusions, and RD exposes
|
|
155
156
|
`rd_zero_variance="correct" | "exclude"`.
|
|
157
|
+
Peto OR uses raw tables for pooling and a separate one-step study estimator;
|
|
158
|
+
it always reports a caution that its approximation is intended for rare
|
|
159
|
+
outcomes, similar within-study arm sizes, and effects that are not large.
|
|
160
|
+
Common-effect MH risk differences use the Sato-Greenland-Robins sampling
|
|
161
|
+
variance; random-effects binary analyses continue to use inverse-variance
|
|
162
|
+
pooling.
|
|
156
163
|
|
|
157
164
|
## Inspect and report
|
|
158
165
|
|
|
@@ -176,7 +183,8 @@ markdown = report.to_markdown()
|
|
|
176
183
|
|
|
177
184
|
OR and RR remain on the log model scale in auditable numeric attributes;
|
|
178
185
|
`display_estimate`, `display_ci`, and `display_prediction_interval` provide
|
|
179
|
-
exponentiated ratios.
|
|
186
|
+
exponentiated ratios. `ZCOR` results similarly retain Fisher's z internally
|
|
187
|
+
and expose back-transformed correlations through the display properties.
|
|
180
188
|
|
|
181
189
|
Rows excluded by missing-value or sparse-data policies remain in
|
|
182
190
|
`study_results` with a stable `row_id`, `included=False`, and an
|
|
@@ -229,7 +237,7 @@ The complete documentation is published at
|
|
|
229
237
|
- [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
|
|
230
238
|
- [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
|
|
231
239
|
- [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
|
|
232
|
-
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/),
|
|
240
|
+
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/), and [correlation](https://zhaoboding.github.io/PyMetaAnalysis/guides/correlation-outcomes/) guides
|
|
233
241
|
- [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
|
|
234
242
|
- [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
|
|
235
243
|
- [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
|
|
@@ -252,7 +260,7 @@ python -m mkdocs serve
|
|
|
252
260
|
|
|
253
261
|
The test suite combines hand calculations, statistical invariants, numerical
|
|
254
262
|
edge cases, and committed R `metafor` reference fixtures. CI covers Python
|
|
255
|
-
3.10–3.
|
|
263
|
+
3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
|
|
256
264
|
distribution builds.
|
|
257
265
|
|
|
258
266
|
This is independent cross-software validation, not a formal external
|
|
@@ -83,8 +83,9 @@ not individual-level or causal effects.
|
|
|
83
83
|
| Input | Effects | Pooling/models |
|
|
84
84
|
| --- | --- | --- |
|
|
85
85
|
| Effect + sampling variance or standard error | Generic | Common/random inverse variance |
|
|
86
|
-
| Two-group events + totals | OR, RR, RD | Common MH OR
|
|
86
|
+
| Two-group events + totals | OR, RR, RD | Common MH; common Peto OR; common/random IV |
|
|
87
87
|
| Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
|
|
88
|
+
| Correlations + sample sizes | Fisher's z (`ZCOR`) | Common/random inverse variance |
|
|
88
89
|
| Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
|
|
89
90
|
|
|
90
91
|
Random-effects inverse-variance models support REML (default), Paule-Mandel,
|
|
@@ -103,6 +104,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
|
|
|
103
104
|
corrections are separate, relative-effect double-zero/double-all rows remain
|
|
104
105
|
visible as exclusions, and RD exposes
|
|
105
106
|
`rd_zero_variance="correct" | "exclude"`.
|
|
107
|
+
Peto OR uses raw tables for pooling and a separate one-step study estimator;
|
|
108
|
+
it always reports a caution that its approximation is intended for rare
|
|
109
|
+
outcomes, similar within-study arm sizes, and effects that are not large.
|
|
110
|
+
Common-effect MH risk differences use the Sato-Greenland-Robins sampling
|
|
111
|
+
variance; random-effects binary analyses continue to use inverse-variance
|
|
112
|
+
pooling.
|
|
106
113
|
|
|
107
114
|
## Inspect and report
|
|
108
115
|
|
|
@@ -126,7 +133,8 @@ markdown = report.to_markdown()
|
|
|
126
133
|
|
|
127
134
|
OR and RR remain on the log model scale in auditable numeric attributes;
|
|
128
135
|
`display_estimate`, `display_ci`, and `display_prediction_interval` provide
|
|
129
|
-
exponentiated ratios.
|
|
136
|
+
exponentiated ratios. `ZCOR` results similarly retain Fisher's z internally
|
|
137
|
+
and expose back-transformed correlations through the display properties.
|
|
130
138
|
|
|
131
139
|
Rows excluded by missing-value or sparse-data policies remain in
|
|
132
140
|
`study_results` with a stable `row_id`, `included=False`, and an
|
|
@@ -179,7 +187,7 @@ The complete documentation is published at
|
|
|
179
187
|
- [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
|
|
180
188
|
- [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
|
|
181
189
|
- [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
|
|
182
|
-
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/),
|
|
190
|
+
- [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/), and [correlation](https://zhaoboding.github.io/PyMetaAnalysis/guides/correlation-outcomes/) guides
|
|
183
191
|
- [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
|
|
184
192
|
- [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
|
|
185
193
|
- [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
|
|
@@ -202,7 +210,7 @@ python -m mkdocs serve
|
|
|
202
210
|
|
|
203
211
|
The test suite combines hand calculations, statistical invariants, numerical
|
|
204
212
|
edge cases, and committed R `metafor` reference fixtures. CI covers Python
|
|
205
|
-
3.10–3.
|
|
213
|
+
3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
|
|
206
214
|
distribution builds.
|
|
207
215
|
|
|
208
216
|
This is independent cross-software validation, not a formal external
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Core performance baseline
|
|
2
2
|
|
|
3
|
-
`benchmark_core.py` measures representative generic, binary, continuous,
|
|
4
|
-
multivariable Meta-regression random-effects fits using
|
|
5
|
-
data. Correctness remains the primary performance
|
|
6
|
-
is intended to reveal large regressions, not to
|
|
7
|
-
threshold.
|
|
3
|
+
`benchmark_core.py` measures representative generic, binary, continuous,
|
|
4
|
+
correlation, and multivariable Meta-regression random-effects fits using
|
|
5
|
+
deterministic synthetic data. Correctness remains the primary performance
|
|
6
|
+
requirement; this benchmark is intended to reveal large regressions, not to
|
|
7
|
+
enforce a fragile wall-clock threshold.
|
|
8
8
|
|
|
9
9
|
Run the default benchmark with:
|
|
10
10
|
|
|
@@ -48,6 +48,8 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
|
|
|
48
48
|
mean_treat = mean_control + rng.normal(0.25, 0.18, size=studies)
|
|
49
49
|
sd_treat = rng.uniform(0.7, 1.6, size=studies)
|
|
50
50
|
sd_control = rng.uniform(0.7, 1.6, size=studies)
|
|
51
|
+
correlation = rng.uniform(-0.65, 0.65, size=studies)
|
|
52
|
+
correlation_n = rng.integers(20, 300, size=studies)
|
|
51
53
|
|
|
52
54
|
return {
|
|
53
55
|
"generic_random_reml": lambda: ma.meta_analysis(
|
|
@@ -77,6 +79,12 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
|
|
|
77
79
|
model="random",
|
|
78
80
|
tau2_method="REML",
|
|
79
81
|
),
|
|
82
|
+
"correlation_random_reml": lambda: ma.meta_correlation(
|
|
83
|
+
correlation=correlation,
|
|
84
|
+
n=correlation_n,
|
|
85
|
+
model="random",
|
|
86
|
+
tau2_method="REML",
|
|
87
|
+
),
|
|
80
88
|
"meta_regression_multivariable_reml": lambda: ma.meta_regression(
|
|
81
89
|
effect=generic_effect,
|
|
82
90
|
variance=generic_variance,
|
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
- Date: 2026-07-15
|
|
5
5
|
- Amendment: the prediction-interval variance decision is superseded by
|
|
6
6
|
[ADR 0004](0004-hartung-knapp-prediction-intervals.md).
|
|
7
|
+
- Amendment: the decision to defer Mantel-Haenszel risk differences is
|
|
8
|
+
superseded by [ADR 0005](0005-mantel-haenszel-risk-difference.md).
|
|
9
|
+
- Amendment: the decision to defer Peto pooling is superseded by
|
|
10
|
+
[ADR 0006](0006-peto-odds-ratio.md).
|
|
7
11
|
|
|
8
12
|
## Context
|
|
9
13
|
|
|
@@ -44,13 +48,15 @@ option, and a provenance transformation.
|
|
|
44
48
|
Mantel-Haenszel pooling remains a common-effect estimator for OR and RR. It
|
|
45
49
|
uses raw tables by default and has a correction setting separate from the one
|
|
46
50
|
used for individual-study effects. Random-effects Mantel-Haenszel, RD
|
|
47
|
-
Mantel-Haenszel, and Peto pooling
|
|
51
|
+
Mantel-Haenszel, and Peto pooling were outside the scope of this original
|
|
52
|
+
decision; ADRs 0005 and 0006 supersede the latter two deferrals.
|
|
48
53
|
|
|
49
54
|
### Heterogeneity
|
|
50
55
|
|
|
51
56
|
Cochran's Q, degrees of freedom, and p-value always use common-effect inverse-
|
|
52
57
|
variance weights. Common-effect and Mantel-Haenszel analyses use Q-based
|
|
53
|
-
I-squared and H-squared.
|
|
58
|
+
I-squared and H-squared. ADR 0006 adds Peto's estimator-specific Q while
|
|
59
|
+
retaining those Q-based inconsistency transformations.
|
|
54
60
|
|
|
55
61
|
Random-effects analyses use:
|
|
56
62
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# ADR 0005: Mantel-Haenszel risk difference
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-08-13
|
|
5
|
+
- Supersedes: the RD exclusion from the Mantel-Haenszel scope in
|
|
6
|
+
[ADR 0002](0002-statistical-policy.md)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
ADR 0002 limited Mantel-Haenszel pooling to common-effect odds ratios and risk
|
|
11
|
+
ratios while the risk-difference estimator and its variance convention were
|
|
12
|
+
still undecided. This left inverse variance as the only pooling method for RD,
|
|
13
|
+
although conventional R implementations provide a common-effect MH RD.
|
|
14
|
+
|
|
15
|
+
The point estimator is straightforward, but several variance estimators have
|
|
16
|
+
appeared in the literature. The selected rule must work under both large-
|
|
17
|
+
stratum and sparse-data limiting models, preserve treatment/control symmetry,
|
|
18
|
+
and remain explicit in reports and cross-software validation.
|
|
19
|
+
|
|
20
|
+
## Decision
|
|
21
|
+
|
|
22
|
+
PyMetaAnalysis supports `measure="RD", method="MH", model="common"`. With
|
|
23
|
+
treatment total `n1_i`, control total `n0_i`, total `N_i`, and
|
|
24
|
+
`w_i = n1_i n0_i / N_i`, the estimate is:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
RD_i = a_i / n1_i - c_i / n0_i
|
|
28
|
+
RD_MH = sum(w_i RD_i) / sum(w_i)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The normal confidence interval uses the Sato-Greenland-Robins sampling
|
|
32
|
+
variance. The resolved method options record
|
|
33
|
+
`mh_rd_variance="Sato-Greenland-Robins"`.
|
|
34
|
+
|
|
35
|
+
Raw tables are used for MH pooling by default. `mh_continuity_correction` and
|
|
36
|
+
`mh_correction_scope` remain the only settings that alter MH pooling tables;
|
|
37
|
+
the separate study-effect correction continues to control displayed study
|
|
38
|
+
uncertainty and the inverse-variance heterogeneity calculation. The existing
|
|
39
|
+
`rd_zero_variance` policy determines whether boundary studies enter all
|
|
40
|
+
synthesis calculations. A non-positive pooled Sato variance raises a domain
|
|
41
|
+
error instead of silently adding a correction.
|
|
42
|
+
|
|
43
|
+
Random-effects MH remains unsupported. Random-effects RD continues to use
|
|
44
|
+
inverse-variance pooling with an explicit tau-squared estimator.
|
|
45
|
+
|
|
46
|
+
## Validation
|
|
47
|
+
|
|
48
|
+
- direct formula tests cover the estimate, Sato variance, weights, and normal
|
|
49
|
+
interval;
|
|
50
|
+
- treatment/control swaps negate the estimate and mirror its interval without
|
|
51
|
+
changing the standard error;
|
|
52
|
+
- row reordering and common count scaling preserve the expected invariants;
|
|
53
|
+
- extreme finite counts exercise the overflow-safe scaled implementation;
|
|
54
|
+
- boundary-policy, explicit-correction, subgroup, leave-one-out, and
|
|
55
|
+
cumulative paths are covered; and
|
|
56
|
+
- fixed-version `metafor::rma.mh(measure="RD")` fixtures cover ordinary,
|
|
57
|
+
sparse, and explicitly corrected tables.
|
|
58
|
+
|
|
59
|
+
## Consequences
|
|
60
|
+
|
|
61
|
+
- common-effect OR, RR, and RD all support MH or inverse-variance pooling;
|
|
62
|
+
- study-table MH weights for RD are proportional to `n1_i n0_i / N_i`;
|
|
63
|
+
- the selected RD variance convention is recoverable from method metadata and
|
|
64
|
+
generated reports; and
|
|
65
|
+
- documentation must continue to distinguish MH RD from random-effects IV RD.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# ADR 0006: Peto one-step odds ratio
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-08-13
|
|
5
|
+
- Supersedes: the Peto deferral in
|
|
6
|
+
[ADR 0002](0002-statistical-policy.md)
|
|
7
|
+
|
|
8
|
+
## Context
|
|
9
|
+
|
|
10
|
+
Peto's one-step method is a conventional common-effect estimator for binary
|
|
11
|
+
outcomes and is particularly associated with rare-event meta-analysis. It is
|
|
12
|
+
not interchangeable with an ordinary inverse-variance odds ratio: it derives
|
|
13
|
+
both the study contribution and pooled estimate from observed-minus-expected
|
|
14
|
+
events and hypergeometric information.
|
|
15
|
+
|
|
16
|
+
The approximation can be biased when treatment and control group sizes differ
|
|
17
|
+
substantially within studies, effects are large, or events are not rare. Its
|
|
18
|
+
zero-cell behavior also differs from ordinary log odds ratios, so pooling and
|
|
19
|
+
display corrections must not be conflated.
|
|
20
|
+
|
|
21
|
+
## Decision
|
|
22
|
+
|
|
23
|
+
PyMetaAnalysis supports `measure="OR", method="Peto", model="common"` with
|
|
24
|
+
`ci_method="normal"`. `"peto_one_step"` is an accepted alias and the resolved
|
|
25
|
+
pooling method is `"peto"`.
|
|
26
|
+
|
|
27
|
+
For stratum `i`, let `O_i = a_i`, `m_i = a_i + c_i`, treatment and control
|
|
28
|
+
totals be `n1_i` and `n0_i`, and `N_i = n1_i + n0_i`. Define:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
E_i = m_i n1_i / N_i
|
|
32
|
+
V_i = m_i (N_i - m_i) n1_i n0_i / (N_i^2 (N_i - 1))
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The individual and pooled model-scale estimates are:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
y_i = (O_i - E_i) / V_i
|
|
39
|
+
Var(y_i) = 1 / V_i
|
|
40
|
+
y_Peto = sum(O_i - E_i) / sum(V_i)
|
|
41
|
+
Var(y_Peto) = 1 / sum(V_i)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Pooling always uses raw 2-by-2 tables. The existing
|
|
45
|
+
`continuity_correction` and `correction_scope` settings affect only displayed
|
|
46
|
+
study estimates and variances; there is no Peto pooling correction parameter.
|
|
47
|
+
Double-zero and double-all rows are excluded before every synthesis
|
|
48
|
+
calculation because they contain no relative-effect information.
|
|
49
|
+
|
|
50
|
+
Peto heterogeneity uses the fitted pooled coefficient and the same
|
|
51
|
+
observed-minus-expected contributions:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
Q = sum(((O_i - E_i) - y_Peto V_i)^2 / V_i)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Q-based I-squared and H-squared follow the project's common-effect
|
|
58
|
+
conventions. Method options record `peto_pooling_tables="raw"` and
|
|
59
|
+
`peto_heterogeneity="O-minus-E"`. Every Peto result carries an approximation
|
|
60
|
+
warning naming the rare-outcome, balanced-arm, and modest-effect conditions.
|
|
61
|
+
|
|
62
|
+
Random-effects Peto and Peto RR/RD are unsupported. Users requesting those
|
|
63
|
+
estimands must select an implemented inverse-variance or Mantel-Haenszel
|
|
64
|
+
combination explicitly.
|
|
65
|
+
|
|
66
|
+
## Validation
|
|
67
|
+
|
|
68
|
+
- direct formula tests cover study estimates, pooled estimate, variance,
|
|
69
|
+
weights, confidence interval, and Peto Q;
|
|
70
|
+
- treatment/control swapping reverses and exponentiates the log-OR limits as
|
|
71
|
+
expected, while row order leaves the fit unchanged;
|
|
72
|
+
- count scaling and extreme finite-count tests exercise overflow-safe
|
|
73
|
+
arithmetic;
|
|
74
|
+
- sparse tables verify that study-level correction does not alter raw Peto
|
|
75
|
+
pooling and that double-zero/double-all rows are excluded; and
|
|
76
|
+
- fixed-version `metafor::escalc(measure="PETO")` and `metafor::rma.peto()`
|
|
77
|
+
fixtures cover ordinary and sparse datasets.
|
|
78
|
+
|
|
79
|
+
## Consequences
|
|
80
|
+
|
|
81
|
+
- common-effect binary OR now offers MH, Peto, and inverse-variance pooling;
|
|
82
|
+
- Peto results remain on the log-OR model scale and use exponentiated display
|
|
83
|
+
values like other OR results;
|
|
84
|
+
- sensitivity, subgroup, provenance, reporting, and plotting workflows reuse
|
|
85
|
+
the same public result contracts; and
|
|
86
|
+
- documentation and reports must preserve the Peto applicability warning
|
|
87
|
+
rather than presenting it as a general sparse-data default.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# ADR 0007: Fisher's z correlation pooling
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-02
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Study-level correlations are common in behavioral, educational, and medical
|
|
9
|
+
research. Directly pooling raw correlations is possible but their sampling
|
|
10
|
+
distribution is bounded, asymmetric away from zero, and has a variance that
|
|
11
|
+
depends on the underlying correlation. Fisher's r-to-z transformation is the
|
|
12
|
+
standard first implementation in R `meta` and `metafor` and composes with the
|
|
13
|
+
library's existing inverse-variance machinery.
|
|
14
|
+
|
|
15
|
+
The API also needs an explicit position on perfect correlations, very small
|
|
16
|
+
samples, displayed values, and multiple correlations drawn from the same
|
|
17
|
+
participants.
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
`meta_correlation()` accepts raw `correlation` and sample size `n`, but its
|
|
22
|
+
first supported measure is only `ZCOR`:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
y_i = atanh(r_i)
|
|
26
|
+
v_i = 1 / (n_i - 3)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
All fitting and heterogeneity calculations use Fisher's z. Result display
|
|
30
|
+
properties and plots use `tanh` to return the correlation scale. The result
|
|
31
|
+
records `effect_scale="fisher_z"`, `display_scale="tanh"`, the transformation,
|
|
32
|
+
variance equation, affected rows, and input sources.
|
|
33
|
+
|
|
34
|
+
Included correlations must be finite and strictly between -1 and 1. Sample
|
|
35
|
+
sizes must be whole numbers of at least 4. The implementation does not clip
|
|
36
|
+
perfect correlations or replace invalid sample sizes because either action
|
|
37
|
+
would introduce an undocumented effect or variance.
|
|
38
|
+
|
|
39
|
+
The default is the library's random-effects inverse-variance policy: REML
|
|
40
|
+
tau-squared and a normal confidence interval. Common effects, PM/DL, the two
|
|
41
|
+
documented Hartung-Knapp options, shared prediction intervals, Q-profile
|
|
42
|
+
heterogeneity intervals, subgroups, repeated-fit sensitivity, reports, and
|
|
43
|
+
plots reuse their existing contracts.
|
|
44
|
+
|
|
45
|
+
Rows are assumed independent. Duplicate labels remain allowed and warned, but
|
|
46
|
+
do not imply a dependence correction. Raw-correlation pooling (`COR`),
|
|
47
|
+
dependent correlations, partial/rank correlations, and reliability
|
|
48
|
+
corrections are deferred.
|
|
49
|
+
|
|
50
|
+
## Validation
|
|
51
|
+
|
|
52
|
+
Committed fixtures generated by `metafor::escalc(measure="ZCOR")` and
|
|
53
|
+
`rma.uni()` validate study effects, variances, common-effect and REML fits,
|
|
54
|
+
weights, and back-transformation. Targeted and property-based tests cover
|
|
55
|
+
domain boundaries, missing rows, sign symmetry, row-order invariance,
|
|
56
|
+
subgroups, sensitivity refits, reports, and Matplotlib coordinates.
|
|
57
|
+
|
|
58
|
+
## Consequences
|
|
59
|
+
|
|
60
|
+
- users can supply pandas columns without calculating z values or variances;
|
|
61
|
+
- model-scale and correlation-scale results remain distinguishable;
|
|
62
|
+
- behavior matches a documented R workflow without importing R at runtime;
|
|
63
|
+
- perfect correlations and samples smaller than four require an upstream,
|
|
64
|
+
scientifically justified decision rather than silent repair;
|
|
65
|
+
- users with dependent correlations must use a method outside the current
|
|
66
|
+
univariate scope.
|
|
@@ -19,7 +19,7 @@ print(ma.__version__)
|
|
|
19
19
|
A provisional citation can use:
|
|
20
20
|
|
|
21
21
|
```text
|
|
22
|
-
|
|
22
|
+
Zhaobo Ding. PyMetaAnalysis (version <version>):
|
|
23
23
|
a pandas-first meta-analysis library for Python.
|
|
24
24
|
https://github.com/ZhaoboDing/PyMetaAnalysis
|
|
25
25
|
```
|
|
@@ -11,7 +11,7 @@ cd PyMetaAnalysis
|
|
|
11
11
|
python -m pip install -e ".[test,dev,docs,plot]"
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Use a supported Python version (3.10–3.
|
|
14
|
+
Use a supported Python version (3.10–3.14). Keep changes focused and preserve
|
|
15
15
|
unrelated worktree modifications.
|
|
16
16
|
|
|
17
17
|
## Run checks
|
|
@@ -31,7 +31,7 @@ python -m build
|
|
|
31
31
|
python tools/inspect_distribution.py dist
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
The CI matrix also tests Python 3.10–3.
|
|
34
|
+
The CI matrix also tests Python 3.10–3.14 and declared dependency lower bounds.
|
|
35
35
|
Install the `notebook` extra before running the notebook executor.
|
|
36
36
|
|
|
37
37
|
## Statistical changes
|
|
@@ -120,8 +120,9 @@ schema, strict JSON behavior, and subgroup reports.
|
|
|
120
120
|
## 6. Understand model and display scales
|
|
121
121
|
|
|
122
122
|
Generic effects, MD, SMD, and RD use the identity scale. OR and RR are modeled
|
|
123
|
-
on a log scale,
|
|
124
|
-
|
|
123
|
+
on a log scale, while `ZCOR` is modeled on Fisher's z scale. Their audit-
|
|
124
|
+
friendly numeric attributes remain on those model scales. Use display
|
|
125
|
+
properties for ratios and back-transformed correlations:
|
|
125
126
|
|
|
126
127
|
```python
|
|
127
128
|
result.display_estimate
|
|
@@ -130,7 +131,8 @@ result.display_prediction_interval
|
|
|
130
131
|
```
|
|
131
132
|
|
|
132
133
|
The [binary-outcome guide](guides/binary-outcomes.md) includes a complete ratio
|
|
133
|
-
example.
|
|
134
|
+
example; the [correlation guide](guides/correlation-outcomes.md) explains the
|
|
135
|
+
Fisher transformation.
|
|
134
136
|
|
|
135
137
|
## 7. Check sensitivity
|
|
136
138
|
|
|
@@ -35,8 +35,33 @@ result = ma.meta_binary(
|
|
|
35
35
|
print(result.summary())
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
Mantel-Haenszel pooling
|
|
39
|
-
`ci_method="normal"`.
|
|
38
|
+
Mantel-Haenszel pooling supports OR, RR, and RD with `model="common"` and
|
|
39
|
+
`ci_method="normal"`. MH risk differences use the Sato-Greenland-Robins
|
|
40
|
+
sampling variance, recorded in `dict(result.method.options)`.
|
|
41
|
+
|
|
42
|
+
## Peto common-effect odds ratio
|
|
43
|
+
|
|
44
|
+
Peto's one-step estimator is an explicit alternative for common-effect OR:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
peto = ma.meta_binary(
|
|
48
|
+
studies,
|
|
49
|
+
event_treat="events_t",
|
|
50
|
+
n_treat="total_t",
|
|
51
|
+
event_control="events_c",
|
|
52
|
+
n_control="total_c",
|
|
53
|
+
measure="OR",
|
|
54
|
+
method="Peto",
|
|
55
|
+
model="common",
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Peto pooling uses the raw 2-by-2 tables and its own observed-minus-expected
|
|
60
|
+
heterogeneity statistic. The study table contains Peto one-step effects;
|
|
61
|
+
`continuity_correction` affects those displayed study effects but not the
|
|
62
|
+
pooled result. Peto is intended for rare outcomes when treatment/control arm
|
|
63
|
+
sizes are similar within studies and effects are not large. The result always
|
|
64
|
+
retains this caveat in `warnings` and Methods text.
|
|
40
65
|
|
|
41
66
|
## Random-effects analysis
|
|
42
67
|
|
|
@@ -71,7 +96,8 @@ them to the generic inverse-variance model.
|
|
|
71
96
|
For OR and RR, `result.estimate` and `result.ci` stay on the log model scale.
|
|
72
97
|
Use `display_estimate` and `display_ci` for exponentiated ratios.
|
|
73
98
|
|
|
74
|
-
RD
|
|
99
|
+
For a common-effect RD, choose either MH or inverse-variance pooling explicitly.
|
|
100
|
+
The MH form is:
|
|
75
101
|
|
|
76
102
|
```python
|
|
77
103
|
result = ma.meta_binary(
|
|
@@ -81,7 +107,7 @@ result = ma.meta_binary(
|
|
|
81
107
|
event_control="events_c",
|
|
82
108
|
n_control="total_c",
|
|
83
109
|
measure="RD",
|
|
84
|
-
method="
|
|
110
|
+
method="MH",
|
|
85
111
|
model="common",
|
|
86
112
|
rd_zero_variance="correct",
|
|
87
113
|
)
|
|
@@ -91,6 +117,8 @@ result = ma.meta_binary(
|
|
|
91
117
|
their raw RD and uses corrected counts only for sampling variance. Use
|
|
92
118
|
`"exclude"` for a protocol that excludes these studies before all synthesis
|
|
93
119
|
calculations. See [zero-event studies](zero-events.md) for details.
|
|
120
|
+
Use `method="IV"` for random-effects RD or when inverse-variance common-effect
|
|
121
|
+
pooling is the prespecified estimator.
|
|
94
122
|
|
|
95
123
|
## Input validation
|
|
96
124
|
|
|
@@ -104,5 +132,5 @@ Sparse tables require additional decisions. Read
|
|
|
104
132
|
settings.
|
|
105
133
|
|
|
106
134
|
See [statistical methods](../methods/statistical-methods.md#binary-study-effects)
|
|
107
|
-
for the OR/RR/RD
|
|
135
|
+
for the OR/RR/RD, Mantel-Haenszel, and Peto equations, and
|
|
108
136
|
[validation](../validation.md) for cross-software coverage.
|