pySEQTarget 0.13.2__tar.gz → 0.13.3__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.
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/PKG-INFO +1 -1
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/SEQopts.py +3 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/_outcome_fit.py +29 -5
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/error/_param_checker.py +3 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget.egg-info/PKG-INFO +1 -1
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pyproject.toml +1 -1
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_followup_options.py +12 -11
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/LICENSE +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/README.md +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/SEQoutput.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/SEQuential.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/_hazard.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/_risk_estimates.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/_subgroup_fit.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/analysis/_survival_pred.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/data/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/error/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/error/_check_separation.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/error/_data_checker.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/_binder.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/_diagnostics.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/_dynamic.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/_mapper.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/expansion/_selection.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_bootstrap.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_col_string.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_fix_categories.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_format_time.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_offloader.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_output_files.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_pad.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_predict_model.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/helpers/_prepare_data.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/initialization/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/initialization/_censoring.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/initialization/_denominator.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/initialization/_numerator.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/initialization/_outcome.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/plot/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/plot/_survival_plot.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/__init__.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_bind.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_data.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_fit.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_offload.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_pred.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget/weighting/_weight_stats.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget.egg-info/SOURCES.txt +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget.egg-info/dependency_links.txt +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget.egg-info/requires.txt +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/pySEQTarget.egg-info/top_level.txt +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/setup.cfg +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_accessor.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_check_separation.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_coefficients.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_covariates.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_expansion.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_fix_categories.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_hazard.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_no_variation.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_offload.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_parallel.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_plot.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_reproducibility.py +0 -0
- {pyseqtarget-0.13.2 → pyseqtarget-0.13.3}/tests/test_survival.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySEQTarget
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.3
|
|
4
4
|
Summary: Sequentially Nested Target Trial Emulation
|
|
5
5
|
Author-email: Ryan O'Dea <ryan.odea@psi.ch>, Alejandro Szmulewicz <aszmulewicz@hsph.harvard.edu>, Tom Palmer <tom.palmer@bristol.ac.uk>, Miguel Hernán <mhernan@hsph.harvard.edu>
|
|
6
6
|
Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>, Tom Palmer <remlapmot@hotmail.com>
|
|
@@ -45,6 +45,8 @@ class SEQopts:
|
|
|
45
45
|
:type followup_include: bool
|
|
46
46
|
:param followup_spline: Boolean to force followup values to be fit to cubic spline
|
|
47
47
|
:type followup_spline: bool
|
|
48
|
+
:param followup_spline_df: Degrees of freedom for the followup cubic spline, default ``4``
|
|
49
|
+
:type followup_spline_df: int
|
|
48
50
|
:param followup_max: Maximum allowed followup in analysis
|
|
49
51
|
:type followup_max: int or None
|
|
50
52
|
:param followup_min: Minimum allowed followup in analysis
|
|
@@ -130,6 +132,7 @@ class SEQopts:
|
|
|
130
132
|
followup_max: int = None
|
|
131
133
|
followup_min: int = 0
|
|
132
134
|
followup_spline: bool = False
|
|
135
|
+
followup_spline_df: int = 4
|
|
133
136
|
hazard_estimate: bool = False
|
|
134
137
|
indicator_baseline: str = "_bas"
|
|
135
138
|
indicator_squared: str = "_sq"
|
|
@@ -1,12 +1,30 @@
|
|
|
1
1
|
import re
|
|
2
2
|
|
|
3
|
+
import numpy as np
|
|
3
4
|
import polars as pl
|
|
4
5
|
import statsmodels.api as sm
|
|
5
6
|
import statsmodels.formula.api as smf
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def
|
|
9
|
-
|
|
9
|
+
def _compute_spline_knots(followup_arr, df=3):
|
|
10
|
+
lower = float(np.min(followup_arr))
|
|
11
|
+
upper = float(np.max(followup_arr))
|
|
12
|
+
n_inner = df - 2
|
|
13
|
+
if n_inner == 0:
|
|
14
|
+
inner_knots = []
|
|
15
|
+
else:
|
|
16
|
+
# Replicate patsy's knot placement: percentiles of unique values in [lower, upper]
|
|
17
|
+
x = np.unique(followup_arr[(lower <= followup_arr) & (followup_arr <= upper)])
|
|
18
|
+
q = np.linspace(0, 100, n_inner + 2)[1:-1]
|
|
19
|
+
inner_knots = np.percentile(x, q.tolist()).tolist()
|
|
20
|
+
return inner_knots, lower, upper
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _apply_spline_formula(formula, indicator_squared, spline_knots):
|
|
24
|
+
inner_knots, lower, upper = spline_knots
|
|
25
|
+
spline = (
|
|
26
|
+
f"cr(followup, knots={inner_knots}, lower_bound={lower}, upper_bound={upper})"
|
|
27
|
+
)
|
|
10
28
|
|
|
11
29
|
formula = re.sub(r"(\w+)\s*\*\s*followup\b", rf"\1*{spline}", formula)
|
|
12
30
|
formula = re.sub(r"\bfollowup\s*\*\s*(\w+)", rf"{spline}*\1", formula)
|
|
@@ -18,8 +36,8 @@ def _apply_spline_formula(formula, indicator_squared):
|
|
|
18
36
|
formula = re.sub(r"^\s*\+\s*|\s*\+\s*$", "", formula).strip()
|
|
19
37
|
|
|
20
38
|
if formula:
|
|
21
|
-
return f"{formula} +
|
|
22
|
-
return
|
|
39
|
+
return f"{formula} + {spline}"
|
|
40
|
+
return spline
|
|
23
41
|
|
|
24
42
|
|
|
25
43
|
def _cast_categories(self, df_pd):
|
|
@@ -64,7 +82,13 @@ def _outcome_fit(
|
|
|
64
82
|
df_pd = _cast_categories(self, df.to_pandas())
|
|
65
83
|
|
|
66
84
|
if self.followup_spline:
|
|
67
|
-
|
|
85
|
+
if getattr(self, "_current_boot_idx", None) is None:
|
|
86
|
+
self._followup_spline_knots = _compute_spline_knots(
|
|
87
|
+
self.DT["followup"].to_numpy(), df=self.followup_spline_df
|
|
88
|
+
)
|
|
89
|
+
formula = _apply_spline_formula(
|
|
90
|
+
formula, self.indicator_squared, self._followup_spline_knots
|
|
91
|
+
)
|
|
68
92
|
|
|
69
93
|
full_formula = f"{outcome} ~ {formula}"
|
|
70
94
|
|
|
@@ -44,6 +44,9 @@ def _param_checker(self):
|
|
|
44
44
|
"Only one of followup_class or followup_include can be set to True."
|
|
45
45
|
)
|
|
46
46
|
|
|
47
|
+
if self.followup_spline_df < 2:
|
|
48
|
+
raise ValueError("followup_spline_df must be at least 2.")
|
|
49
|
+
|
|
47
50
|
if (
|
|
48
51
|
self.weighted
|
|
49
52
|
and self.method == "ITT"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySEQTarget
|
|
3
|
-
Version: 0.13.
|
|
3
|
+
Version: 0.13.3
|
|
4
4
|
Summary: Sequentially Nested Target Trial Emulation
|
|
5
5
|
Author-email: Ryan O'Dea <ryan.odea@psi.ch>, Alejandro Szmulewicz <aszmulewicz@hsph.harvard.edu>, Tom Palmer <tom.palmer@bristol.ac.uk>, Miguel Hernán <mhernan@hsph.harvard.edu>
|
|
6
6
|
Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>, Tom Palmer <remlapmot@hotmail.com>
|
|
@@ -57,17 +57,18 @@ def test_followup_spline():
|
|
|
57
57
|
s.fit()
|
|
58
58
|
matrix = s.outcome_model[0]["outcome"].summary2().tables[1]["Coef."].to_list()
|
|
59
59
|
expected = [
|
|
60
|
-
-
|
|
61
|
-
0.
|
|
62
|
-
0.
|
|
63
|
-
0.
|
|
64
|
-
0.
|
|
65
|
-
0.
|
|
66
|
-
-0.
|
|
67
|
-
0.
|
|
68
|
-
-
|
|
69
|
-
|
|
70
|
-
|
|
60
|
+
-4.804282252748607,
|
|
61
|
+
0.19115933860001255,
|
|
62
|
+
0.12717121164606823,
|
|
63
|
+
0.044310717515918724,
|
|
64
|
+
0.0005814999431447507,
|
|
65
|
+
0.0032948355025455216,
|
|
66
|
+
-0.013371824500839971,
|
|
67
|
+
0.19972467861548412,
|
|
68
|
+
-2.027245615586753,
|
|
69
|
+
-1.395729861856384,
|
|
70
|
+
-0.9397731941281695,
|
|
71
|
+
-0.4415335811772879,
|
|
71
72
|
]
|
|
72
73
|
assert [round(x, 3) for x in matrix] == [round(x, 3) for x in expected]
|
|
73
74
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|