PyMetaAnalysis 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
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.
- meta_analyze/__init__.py +14 -0
- meta_analyze/_version.py +1 -1
- meta_analyze/regression_api.py +37 -3
- meta_analyze/regression_collinearity.py +304 -0
- meta_analyze/regression_contrasts.py +365 -0
- meta_analyze/regression_results.py +67 -1
- meta_analyze/regression_sensitivity.py +587 -0
- {pymetaanalysis-0.3.0.dist-info → pymetaanalysis-0.4.0.dist-info}/METADATA +29 -6
- {pymetaanalysis-0.3.0.dist-info → pymetaanalysis-0.4.0.dist-info}/RECORD +11 -8
- {pymetaanalysis-0.3.0.dist-info → pymetaanalysis-0.4.0.dist-info}/WHEEL +0 -0
- {pymetaanalysis-0.3.0.dist-info → pymetaanalysis-0.4.0.dist-info}/licenses/LICENSE +0 -0
meta_analyze/__init__.py
CHANGED
|
@@ -19,12 +19,21 @@ from .provenance import (
|
|
|
19
19
|
TransformationRecord,
|
|
20
20
|
)
|
|
21
21
|
from .regression_api import meta_regression
|
|
22
|
+
from .regression_collinearity import MetaRegressionCollinearityResult
|
|
23
|
+
from .regression_contrasts import (
|
|
24
|
+
LinearContrastTestResult,
|
|
25
|
+
MetaRegressionContrastResult,
|
|
26
|
+
)
|
|
22
27
|
from .regression_results import (
|
|
23
28
|
MetaRegressionDiagnostics,
|
|
24
29
|
MetaRegressionResult,
|
|
25
30
|
MetaRegressionSummary,
|
|
26
31
|
ModeratorTestResult,
|
|
27
32
|
)
|
|
33
|
+
from .regression_sensitivity import (
|
|
34
|
+
MetaRegressionInfluenceResult,
|
|
35
|
+
MetaRegressionLeaveOneOutResult,
|
|
36
|
+
)
|
|
28
37
|
from .reporting import ResultReport
|
|
29
38
|
from .results import (
|
|
30
39
|
FitDiagnostics,
|
|
@@ -52,10 +61,15 @@ __all__ = [
|
|
|
52
61
|
"InputFieldProvenance",
|
|
53
62
|
"InvalidStudyDataError",
|
|
54
63
|
"LeaveOneOutResult",
|
|
64
|
+
"LinearContrastTestResult",
|
|
55
65
|
"MetaAnalysisError",
|
|
56
66
|
"MetaAnalysisResult",
|
|
57
67
|
"MetaAnalysisSummary",
|
|
68
|
+
"MetaRegressionCollinearityResult",
|
|
69
|
+
"MetaRegressionContrastResult",
|
|
58
70
|
"MetaRegressionDiagnostics",
|
|
71
|
+
"MetaRegressionInfluenceResult",
|
|
72
|
+
"MetaRegressionLeaveOneOutResult",
|
|
59
73
|
"MetaRegressionMethodConfig",
|
|
60
74
|
"MetaRegressionResult",
|
|
61
75
|
"MetaRegressionSummary",
|
meta_analyze/_version.py
CHANGED
meta_analyze/regression_api.py
CHANGED
|
@@ -21,7 +21,7 @@ from .estimators import (
|
|
|
21
21
|
fit_meta_regression,
|
|
22
22
|
residual_heterogeneity,
|
|
23
23
|
)
|
|
24
|
-
from .exceptions import UnsupportedMethodError
|
|
24
|
+
from .exceptions import InsufficientStudiesError, UnsupportedMethodError
|
|
25
25
|
from .provenance import TransformationRecord, build_analysis_provenance
|
|
26
26
|
from .regression_results import (
|
|
27
27
|
MetaRegressionDiagnostics,
|
|
@@ -62,6 +62,22 @@ def _normalize_inference_method(inference_method: str) -> str:
|
|
|
62
62
|
return aliases.get(normalized, normalized)
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
def _normalize_prediction_interval_method(method: str) -> str:
|
|
66
|
+
normalized = method.lower().replace("-", "_")
|
|
67
|
+
aliases = {
|
|
68
|
+
"default": "normal_or_t_k_minus_p",
|
|
69
|
+
"normal_or_t_k_minus_p": "normal_or_t_k_minus_p",
|
|
70
|
+
"riley": "riley",
|
|
71
|
+
}
|
|
72
|
+
try:
|
|
73
|
+
return aliases[normalized]
|
|
74
|
+
except KeyError as error:
|
|
75
|
+
raise UnsupportedMethodError(
|
|
76
|
+
"Unsupported prediction_interval_method="
|
|
77
|
+
f"{method!r}; expected 'default' or 'riley'."
|
|
78
|
+
) from error
|
|
79
|
+
|
|
80
|
+
|
|
65
81
|
def _moderator_inputs(
|
|
66
82
|
moderators: ModeratorInput,
|
|
67
83
|
) -> tuple[tuple[str, ColumnOrArray], ...]:
|
|
@@ -86,6 +102,7 @@ def meta_regression(
|
|
|
86
102
|
inference_method: str = "normal",
|
|
87
103
|
intercept: bool = True,
|
|
88
104
|
confidence_level: float = 0.95,
|
|
105
|
+
prediction_interval_method: str = "default",
|
|
89
106
|
missing: MissingPolicy = "raise",
|
|
90
107
|
atol: float = 1e-10,
|
|
91
108
|
max_iter: int = 1000,
|
|
@@ -97,7 +114,9 @@ def meta_regression(
|
|
|
97
114
|
moderators must be declared explicitly as ordered level sequences; the
|
|
98
115
|
first level is the treatment-coding reference. Coefficients describe
|
|
99
116
|
study-level associations and do not establish individual-level or causal
|
|
100
|
-
effects.
|
|
117
|
+
effects. Mixed-effects true-effect prediction intervals use the fitted
|
|
118
|
+
inference distribution by default; ``prediction_interval_method="riley"``
|
|
119
|
+
selects a t critical value with ``k-p-1`` degrees of freedom.
|
|
101
120
|
"""
|
|
102
121
|
|
|
103
122
|
confidence_level, atol, max_iter = _validate_analysis_controls(
|
|
@@ -107,7 +126,14 @@ def meta_regression(
|
|
|
107
126
|
)
|
|
108
127
|
normalized_model = _normalize_regression_model(model)
|
|
109
128
|
normalized_inference = _normalize_inference_method(inference_method)
|
|
129
|
+
normalized_prediction_interval = _normalize_prediction_interval_method(
|
|
130
|
+
prediction_interval_method
|
|
131
|
+
)
|
|
110
132
|
normalized_tau2 = tau2_method.upper().replace("-", "_")
|
|
133
|
+
if normalized_model == "common" and normalized_prediction_interval == "riley":
|
|
134
|
+
raise UnsupportedMethodError(
|
|
135
|
+
"prediction_interval_method='riley' requires a mixed-effects model."
|
|
136
|
+
)
|
|
111
137
|
|
|
112
138
|
normalized = normalize_meta_regression_data(
|
|
113
139
|
data=data,
|
|
@@ -123,6 +149,14 @@ def meta_regression(
|
|
|
123
149
|
included_effect = normalized.included_effect
|
|
124
150
|
included_variance = normalized.included_variance
|
|
125
151
|
design = normalized.included_design_matrix
|
|
152
|
+
if (
|
|
153
|
+
normalized_prediction_interval == "riley"
|
|
154
|
+
and len(included_effect) - design.shape[1] <= 1
|
|
155
|
+
):
|
|
156
|
+
raise InsufficientStudiesError(
|
|
157
|
+
"prediction_interval_method='riley' requires at least two residual "
|
|
158
|
+
"degrees of freedom (k-p >= 2)."
|
|
159
|
+
)
|
|
126
160
|
fit = fit_meta_regression(
|
|
127
161
|
included_effect,
|
|
128
162
|
included_variance,
|
|
@@ -342,7 +376,7 @@ def meta_regression(
|
|
|
342
376
|
if spec.kind == "categorical"
|
|
343
377
|
),
|
|
344
378
|
prediction_interval_method=(
|
|
345
|
-
|
|
379
|
+
normalized_prediction_interval if normalized_model == "mixed" else None
|
|
346
380
|
),
|
|
347
381
|
missing=missing,
|
|
348
382
|
atol=atol,
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"""Collinearity diagnostics for fitted meta-regression models."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
from numpy.typing import NDArray
|
|
11
|
+
|
|
12
|
+
from .exceptions import InvalidStudyDataError
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from .regression_results import MetaRegressionResult
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True, slots=True)
|
|
19
|
+
class MetaRegressionCollinearityResult:
|
|
20
|
+
"""VIF/GVIF and weighted condition diagnostics for a fitted design."""
|
|
21
|
+
|
|
22
|
+
original: MetaRegressionResult
|
|
23
|
+
raw_condition_number: float
|
|
24
|
+
weighted_scaled_condition_number: float
|
|
25
|
+
condition_index_reference: float
|
|
26
|
+
variance_proportion_reference: float
|
|
27
|
+
warnings: tuple[str, ...]
|
|
28
|
+
_term_vif: pd.DataFrame = field(repr=False, compare=False)
|
|
29
|
+
_moderator_gvif: pd.DataFrame = field(repr=False, compare=False)
|
|
30
|
+
_condition_indices: pd.DataFrame = field(repr=False, compare=False)
|
|
31
|
+
_variance_proportions: pd.DataFrame = field(repr=False, compare=False)
|
|
32
|
+
|
|
33
|
+
def __post_init__(self) -> None:
|
|
34
|
+
object.__setattr__(self, "_term_vif", self._term_vif.copy(deep=True))
|
|
35
|
+
object.__setattr__(
|
|
36
|
+
self, "_moderator_gvif", self._moderator_gvif.copy(deep=True)
|
|
37
|
+
)
|
|
38
|
+
object.__setattr__(
|
|
39
|
+
self, "_condition_indices", self._condition_indices.copy(deep=True)
|
|
40
|
+
)
|
|
41
|
+
object.__setattr__(
|
|
42
|
+
self,
|
|
43
|
+
"_variance_proportions",
|
|
44
|
+
self._variance_proportions.copy(deep=True),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def term_vif(self) -> pd.DataFrame:
|
|
49
|
+
"""Return VIF and standard-error inflation for encoded terms."""
|
|
50
|
+
|
|
51
|
+
return self._term_vif.copy(deep=True)
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def moderator_gvif(self) -> pd.DataFrame:
|
|
55
|
+
"""Return moderator-level GVIF and dimension-adjusted GSIF."""
|
|
56
|
+
|
|
57
|
+
return self._moderator_gvif.copy(deep=True)
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def condition_indices(self) -> pd.DataFrame:
|
|
61
|
+
"""Return singular-value dimensions and their condition indices."""
|
|
62
|
+
|
|
63
|
+
return self._condition_indices.copy(deep=True)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def variance_proportions(self) -> pd.DataFrame:
|
|
67
|
+
"""Return long-form coefficient variance-decomposition proportions."""
|
|
68
|
+
|
|
69
|
+
return self._variance_proportions.copy(deep=True)
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def concerning_dimensions(self) -> pd.DataFrame:
|
|
73
|
+
"""Return dimensions meeting both documented collinearity references."""
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
self._condition_indices.loc[lambda frame: frame["concerning"]]
|
|
77
|
+
.reset_index(drop=True)
|
|
78
|
+
.copy(deep=True)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _classic_covariance(result: MetaRegressionResult) -> NDArray[np.float64]:
|
|
83
|
+
studies = result.study_results
|
|
84
|
+
included = studies["included"].to_numpy(dtype=np.bool_, copy=True)
|
|
85
|
+
variance = studies.loc[included, "variance"].to_numpy(dtype=np.float64, copy=True)
|
|
86
|
+
design = result.design_matrix.to_numpy(dtype=np.float64, copy=True)
|
|
87
|
+
denominator = variance + result.tau2
|
|
88
|
+
variance_scale = float(np.min(denominator))
|
|
89
|
+
relative_weights = variance_scale / denominator
|
|
90
|
+
gram = design.T @ (relative_weights[:, np.newaxis] * design)
|
|
91
|
+
try:
|
|
92
|
+
inverse = np.linalg.solve(gram, np.eye(gram.shape[0]))
|
|
93
|
+
except np.linalg.LinAlgError as error: # pragma: no cover - fit is full rank
|
|
94
|
+
raise InvalidStudyDataError(
|
|
95
|
+
"Meta-regression coefficient covariance could not be reconstructed."
|
|
96
|
+
) from error
|
|
97
|
+
inverse = 0.5 * (inverse + inverse.T)
|
|
98
|
+
return variance_scale * inverse
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _covariance_correlation(
|
|
102
|
+
covariance: NDArray[np.float64],
|
|
103
|
+
) -> NDArray[np.float64]:
|
|
104
|
+
diagonal = np.diag(covariance)
|
|
105
|
+
if np.any(diagonal <= 0.0):
|
|
106
|
+
raise InvalidStudyDataError(
|
|
107
|
+
"VIF diagnostics require positive coefficient variances."
|
|
108
|
+
)
|
|
109
|
+
standard_errors = np.sqrt(diagonal)
|
|
110
|
+
correlation = covariance / np.outer(standard_errors, standard_errors)
|
|
111
|
+
correlation = 0.5 * (correlation + correlation.T)
|
|
112
|
+
np.fill_diagonal(correlation, 1.0)
|
|
113
|
+
return np.asarray(correlation, dtype=np.float64)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _log_determinant(
|
|
117
|
+
matrix: NDArray[np.float64], positions: NDArray[np.int64]
|
|
118
|
+
) -> float:
|
|
119
|
+
if positions.size == 0:
|
|
120
|
+
return 0.0
|
|
121
|
+
selected = matrix[np.ix_(positions, positions)]
|
|
122
|
+
sign, value = np.linalg.slogdet(selected)
|
|
123
|
+
if sign <= 0.0:
|
|
124
|
+
raise InvalidStudyDataError(
|
|
125
|
+
"VIF diagnostics require a positive-definite coefficient "
|
|
126
|
+
"correlation matrix."
|
|
127
|
+
)
|
|
128
|
+
return float(value)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _gvif(correlation: NDArray[np.float64], positions: NDArray[np.int64]) -> float:
|
|
132
|
+
all_positions = np.arange(correlation.shape[0], dtype=np.int64)
|
|
133
|
+
complement = all_positions[~np.isin(all_positions, positions)]
|
|
134
|
+
log_gvif = (
|
|
135
|
+
_log_determinant(correlation, positions)
|
|
136
|
+
+ _log_determinant(correlation, complement)
|
|
137
|
+
- _log_determinant(correlation, all_positions)
|
|
138
|
+
)
|
|
139
|
+
if log_gvif >= np.log(np.finfo(np.float64).max):
|
|
140
|
+
return float("inf")
|
|
141
|
+
return max(1.0, float(np.exp(log_gvif)))
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _vif_tables(
|
|
145
|
+
result: MetaRegressionResult,
|
|
146
|
+
covariance: NDArray[np.float64],
|
|
147
|
+
) -> tuple[pd.DataFrame, pd.DataFrame]:
|
|
148
|
+
offset = 1 if result.design_info.intercept else 0
|
|
149
|
+
terms = result.design_info.term_names[offset:]
|
|
150
|
+
correlation = _covariance_correlation(covariance[offset:, offset:])
|
|
151
|
+
moderator_for_term = {
|
|
152
|
+
term: spec.name
|
|
153
|
+
for spec in result.design_info.moderators
|
|
154
|
+
for term in spec.term_names
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
term_rows: list[dict[str, object]] = []
|
|
158
|
+
for position, term in enumerate(terms):
|
|
159
|
+
vif = _gvif(correlation, np.asarray([position], dtype=np.int64))
|
|
160
|
+
term_rows.append(
|
|
161
|
+
{
|
|
162
|
+
"term": term,
|
|
163
|
+
"moderator": moderator_for_term[term],
|
|
164
|
+
"vif": vif,
|
|
165
|
+
"sif": float(np.sqrt(vif)),
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
moderator_rows: list[dict[str, object]] = []
|
|
170
|
+
for spec in result.design_info.moderators:
|
|
171
|
+
positions = np.asarray(
|
|
172
|
+
[terms.index(term) for term in spec.term_names], dtype=np.int64
|
|
173
|
+
)
|
|
174
|
+
gvif = _gvif(correlation, positions)
|
|
175
|
+
term_count = len(positions)
|
|
176
|
+
moderator_rows.append(
|
|
177
|
+
{
|
|
178
|
+
"moderator": spec.name,
|
|
179
|
+
"kind": spec.kind,
|
|
180
|
+
"terms": spec.term_names,
|
|
181
|
+
"term_count": term_count,
|
|
182
|
+
"gvif": gvif,
|
|
183
|
+
"gsif": float(gvif ** (1.0 / (2.0 * term_count))),
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
return pd.DataFrame(term_rows), pd.DataFrame(moderator_rows)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _condition_tables(
|
|
190
|
+
result: MetaRegressionResult,
|
|
191
|
+
*,
|
|
192
|
+
condition_reference: float,
|
|
193
|
+
variance_reference: float,
|
|
194
|
+
) -> tuple[pd.DataFrame, pd.DataFrame, float]:
|
|
195
|
+
studies = result.study_results
|
|
196
|
+
included = studies["included"].to_numpy(dtype=np.bool_, copy=True)
|
|
197
|
+
variance = studies.loc[included, "variance"].to_numpy(dtype=np.float64, copy=True)
|
|
198
|
+
design = result.design_matrix.to_numpy(dtype=np.float64, copy=True)
|
|
199
|
+
weights = 1.0 / (variance + result.tau2)
|
|
200
|
+
weighted_design = np.sqrt(weights)[:, np.newaxis] * design
|
|
201
|
+
column_norms = np.linalg.norm(weighted_design, axis=0)
|
|
202
|
+
if np.any(column_norms == 0.0): # pragma: no cover - full rank checked at fit
|
|
203
|
+
raise InvalidStudyDataError(
|
|
204
|
+
"Condition diagnostics require nonzero weighted design columns."
|
|
205
|
+
)
|
|
206
|
+
scaled_design = weighted_design / column_norms
|
|
207
|
+
_, singular_values, right_vectors_transposed = np.linalg.svd(
|
|
208
|
+
scaled_design, full_matrices=False
|
|
209
|
+
)
|
|
210
|
+
eigenvalues = singular_values * singular_values
|
|
211
|
+
condition_indices = singular_values[0] / singular_values
|
|
212
|
+
variance_components = (
|
|
213
|
+
right_vectors_transposed.T * right_vectors_transposed.T
|
|
214
|
+
) / eigenvalues[np.newaxis, :]
|
|
215
|
+
variance_proportions = variance_components / np.sum(
|
|
216
|
+
variance_components, axis=1, keepdims=True
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
condition_rows: list[dict[str, object]] = []
|
|
220
|
+
variance_rows: list[dict[str, object]] = []
|
|
221
|
+
term_to_moderator = {
|
|
222
|
+
term: spec.name
|
|
223
|
+
for spec in result.design_info.moderators
|
|
224
|
+
for term in spec.term_names
|
|
225
|
+
}
|
|
226
|
+
for position, (singular_value, eigenvalue, condition_index) in enumerate(
|
|
227
|
+
zip(singular_values, eigenvalues, condition_indices, strict=True), start=1
|
|
228
|
+
):
|
|
229
|
+
high_variance_count = int(
|
|
230
|
+
np.count_nonzero(variance_proportions[:, position - 1] > variance_reference)
|
|
231
|
+
)
|
|
232
|
+
high_condition = bool(condition_index > condition_reference)
|
|
233
|
+
concerning = bool(high_condition and high_variance_count >= 2)
|
|
234
|
+
condition_rows.append(
|
|
235
|
+
{
|
|
236
|
+
"dimension": position,
|
|
237
|
+
"singular_value": singular_value,
|
|
238
|
+
"eigenvalue": eigenvalue,
|
|
239
|
+
"condition_index": condition_index,
|
|
240
|
+
"high_condition_index": high_condition,
|
|
241
|
+
"high_variance_term_count": high_variance_count,
|
|
242
|
+
"concerning": concerning,
|
|
243
|
+
}
|
|
244
|
+
)
|
|
245
|
+
for term, proportion in zip(
|
|
246
|
+
result.design_info.term_names,
|
|
247
|
+
variance_proportions[:, position - 1],
|
|
248
|
+
strict=True,
|
|
249
|
+
):
|
|
250
|
+
variance_rows.append(
|
|
251
|
+
{
|
|
252
|
+
"dimension": position,
|
|
253
|
+
"condition_index": condition_index,
|
|
254
|
+
"term": term,
|
|
255
|
+
"moderator": term_to_moderator.get(term),
|
|
256
|
+
"variance_proportion": proportion,
|
|
257
|
+
"high_variance_proportion": bool(proportion > variance_reference),
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
return (
|
|
261
|
+
pd.DataFrame(condition_rows),
|
|
262
|
+
pd.DataFrame(variance_rows),
|
|
263
|
+
float(condition_indices[-1]),
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def meta_regression_collinearity(
|
|
268
|
+
result: MetaRegressionResult,
|
|
269
|
+
) -> MetaRegressionCollinearityResult:
|
|
270
|
+
"""Compute coefficient inflation and weighted design diagnostics."""
|
|
271
|
+
|
|
272
|
+
condition_reference = 30.0
|
|
273
|
+
variance_reference = 0.5
|
|
274
|
+
covariance = _classic_covariance(result)
|
|
275
|
+
term_vif, moderator_gvif = _vif_tables(result, covariance)
|
|
276
|
+
condition_indices, variance_proportions, condition_number = _condition_tables(
|
|
277
|
+
result,
|
|
278
|
+
condition_reference=condition_reference,
|
|
279
|
+
variance_reference=variance_reference,
|
|
280
|
+
)
|
|
281
|
+
warnings: list[str] = []
|
|
282
|
+
if condition_indices["high_condition_index"].any():
|
|
283
|
+
warnings.append(
|
|
284
|
+
"At least one weighted, column-scaled condition index exceeds the "
|
|
285
|
+
"heuristic reference of 30; inspect variance-decomposition "
|
|
286
|
+
"proportions."
|
|
287
|
+
)
|
|
288
|
+
if condition_indices["concerning"].any():
|
|
289
|
+
warnings.append(
|
|
290
|
+
"At least one high-condition dimension concentrates more than 50% "
|
|
291
|
+
"of the coefficient variance for multiple terms."
|
|
292
|
+
)
|
|
293
|
+
return MetaRegressionCollinearityResult(
|
|
294
|
+
original=result,
|
|
295
|
+
raw_condition_number=result.diagnostics.condition_number,
|
|
296
|
+
weighted_scaled_condition_number=condition_number,
|
|
297
|
+
condition_index_reference=condition_reference,
|
|
298
|
+
variance_proportion_reference=variance_reference,
|
|
299
|
+
warnings=tuple(warnings),
|
|
300
|
+
_term_vif=term_vif,
|
|
301
|
+
_moderator_gvif=moderator_gvif,
|
|
302
|
+
_condition_indices=condition_indices,
|
|
303
|
+
_variance_proportions=variance_proportions,
|
|
304
|
+
)
|