pySEQTarget 0.10.0__tar.gz → 0.10.1__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.10.0 → pyseqtarget-0.10.1}/PKG-INFO +6 -5
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/README.md +5 -4
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/SEQuential.py +6 -6
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/__init__.py +1 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/_survival_pred.py +8 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/error/__init__.py +1 -1
- pyseqtarget-0.10.0/pySEQTarget/error/_datachecker.py → pyseqtarget-0.10.1/pySEQTarget/error/_data_checker.py +1 -1
- pyseqtarget-0.10.1/pySEQTarget/expansion/_selection.py +44 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_bootstrap.py +2 -1
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/_weight_fit.py +2 -2
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/_weight_pred.py +4 -4
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget.egg-info/PKG-INFO +6 -5
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget.egg-info/SOURCES.txt +1 -1
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pyproject.toml +1 -1
- pyseqtarget-0.10.0/pySEQTarget/expansion/_selection.py +0 -31
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/LICENSE +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/SEQopts.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/SEQoutput.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/_hazard.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/_outcome_fit.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/_risk_estimates.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/analysis/_subgroup_fit.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/data/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/error/_param_checker.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/expansion/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/expansion/_binder.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/expansion/_diagnostics.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/expansion/_dynamic.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/expansion/_mapper.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_col_string.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_format_time.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_output_files.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_pad.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_predict_model.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/helpers/_prepare_data.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/initialization/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/initialization/_censoring.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/initialization/_denominator.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/initialization/_numerator.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/initialization/_outcome.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/plot/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/plot/_survival_plot.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/__init__.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/_weight_bind.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/_weight_data.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget/weighting/_weight_stats.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget.egg-info/dependency_links.txt +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget.egg-info/requires.txt +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/pySEQTarget.egg-info/top_level.txt +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/setup.cfg +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_accessor.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_coefficients.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_covariates.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_followup_options.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_hazard.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_parallel.py +0 -0
- {pyseqtarget-0.10.0 → pyseqtarget-0.10.1}/tests/test_survival.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySEQTarget
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.1
|
|
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 Hernan <mhernan@hsph.harvard.edu>
|
|
6
6
|
Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>
|
|
@@ -68,8 +68,9 @@ From the user side, this amounts to creating a dataclass, `SEQopts`, and then fe
|
|
|
68
68
|
```python
|
|
69
69
|
import polars as pl
|
|
70
70
|
from pySEQTarget import SEQuential, SEQopts
|
|
71
|
+
from pySEQTarget.data import load_data
|
|
71
72
|
|
|
72
|
-
data =
|
|
73
|
+
data = load_data("SEQdata")
|
|
73
74
|
options = SEQopts(km_curves = True)
|
|
74
75
|
|
|
75
76
|
# Initiate the class
|
|
@@ -77,17 +78,18 @@ model = SEQuential(data,
|
|
|
77
78
|
id_col = "ID",
|
|
78
79
|
time_col = "time",
|
|
79
80
|
eligible_col = "eligible",
|
|
81
|
+
treatment_col = "tx_init",
|
|
82
|
+
outcome_col = "outcome",
|
|
80
83
|
time_varying_cols = ["N", "L", "P"],
|
|
81
84
|
fixed_cols = ["sex"],
|
|
82
85
|
method = "ITT",
|
|
83
|
-
|
|
86
|
+
parameters = options)
|
|
84
87
|
model.expand() # Construct the nested structure
|
|
85
88
|
model.bootstrap(bootstrap_nboot = 20) # Run 20 bootstrap samples
|
|
86
89
|
model.fit() # Fit the model
|
|
87
90
|
model.survival() # Create survival curves
|
|
88
91
|
model.plot() # Create and show a plot of the survival curves
|
|
89
92
|
model.collect() # Collection of important information
|
|
90
|
-
|
|
91
93
|
```
|
|
92
94
|
|
|
93
95
|
## Assumptions
|
|
@@ -95,4 +97,3 @@ There are several key assumptions in this package -
|
|
|
95
97
|
1. User provided `time_col` begins at 0 per unique `id_col`, we also assume this column contains only integers and continues by 1 for every time step, e.g. (0, 1, 2, 3, 4, ...) is allowed and (0, 1, 2, 2.5, ...) or (0, 1, 4, 5) are not
|
|
96
98
|
1. Provided `time_col` entries may be out of order at intake as a sort is enforced at expansion.
|
|
97
99
|
2. `eligible_col` and elements of `excused_colnames` are once 1, only 1 (with respect to `time_col`) flag variables.
|
|
98
|
-
|
|
@@ -31,8 +31,9 @@ From the user side, this amounts to creating a dataclass, `SEQopts`, and then fe
|
|
|
31
31
|
```python
|
|
32
32
|
import polars as pl
|
|
33
33
|
from pySEQTarget import SEQuential, SEQopts
|
|
34
|
+
from pySEQTarget.data import load_data
|
|
34
35
|
|
|
35
|
-
data =
|
|
36
|
+
data = load_data("SEQdata")
|
|
36
37
|
options = SEQopts(km_curves = True)
|
|
37
38
|
|
|
38
39
|
# Initiate the class
|
|
@@ -40,17 +41,18 @@ model = SEQuential(data,
|
|
|
40
41
|
id_col = "ID",
|
|
41
42
|
time_col = "time",
|
|
42
43
|
eligible_col = "eligible",
|
|
44
|
+
treatment_col = "tx_init",
|
|
45
|
+
outcome_col = "outcome",
|
|
43
46
|
time_varying_cols = ["N", "L", "P"],
|
|
44
47
|
fixed_cols = ["sex"],
|
|
45
48
|
method = "ITT",
|
|
46
|
-
|
|
49
|
+
parameters = options)
|
|
47
50
|
model.expand() # Construct the nested structure
|
|
48
51
|
model.bootstrap(bootstrap_nboot = 20) # Run 20 bootstrap samples
|
|
49
52
|
model.fit() # Fit the model
|
|
50
53
|
model.survival() # Create survival curves
|
|
51
54
|
model.plot() # Create and show a plot of the survival curves
|
|
52
55
|
model.collect() # Collection of important information
|
|
53
|
-
|
|
54
56
|
```
|
|
55
57
|
|
|
56
58
|
## Assumptions
|
|
@@ -58,4 +60,3 @@ There are several key assumptions in this package -
|
|
|
58
60
|
1. User provided `time_col` begins at 0 per unique `id_col`, we also assume this column contains only integers and continues by 1 for every time step, e.g. (0, 1, 2, 3, 4, ...) is allowed and (0, 1, 2, 2.5, ...) or (0, 1, 4, 5) are not
|
|
59
61
|
1. Provided `time_col` entries may be out of order at intake as a sort is enforced at expansion.
|
|
60
62
|
2. `eligible_col` and elements of `excused_colnames` are once 1, only 1 (with respect to `time_col`) flag variables.
|
|
61
|
-
|
|
@@ -7,9 +7,10 @@ from typing import List, Literal, Optional
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import polars as pl
|
|
9
9
|
|
|
10
|
-
from .analysis import (_calculate_hazard, _calculate_survival,
|
|
11
|
-
_pred_risk, _risk_estimates,
|
|
12
|
-
|
|
10
|
+
from .analysis import (_calculate_hazard, _calculate_survival, _clamp,
|
|
11
|
+
_outcome_fit, _pred_risk, _risk_estimates,
|
|
12
|
+
_subgroup_fit)
|
|
13
|
+
from .error import _data_checker, _param_checker
|
|
13
14
|
from .expansion import _binder, _diagnostics, _dynamic, _random_selection
|
|
14
15
|
from .helpers import _col_string, _format_time, bootstrap_loop
|
|
15
16
|
from .initialization import (_cense_denominator, _cense_numerator,
|
|
@@ -101,7 +102,7 @@ class SEQuential:
|
|
|
101
102
|
self.cense_denominator = _cense_denominator(self)
|
|
102
103
|
|
|
103
104
|
_param_checker(self)
|
|
104
|
-
|
|
105
|
+
_data_checker(self)
|
|
105
106
|
|
|
106
107
|
def expand(self) -> None:
|
|
107
108
|
"""
|
|
@@ -190,7 +191,6 @@ class SEQuential:
|
|
|
190
191
|
)
|
|
191
192
|
id_counts = Counter(sampled_IDs)
|
|
192
193
|
self._boot_samples.append(id_counts)
|
|
193
|
-
return self
|
|
194
194
|
|
|
195
195
|
@bootstrap_loop
|
|
196
196
|
def fit(self) -> None:
|
|
@@ -266,7 +266,7 @@ class SEQuential:
|
|
|
266
266
|
|
|
267
267
|
risk_data = _pred_risk(self)
|
|
268
268
|
surv_data = _calculate_survival(self, risk_data)
|
|
269
|
-
self.km_data = pl.concat([risk_data, surv_data])
|
|
269
|
+
self.km_data = _clamp(pl.concat([risk_data, surv_data]))
|
|
270
270
|
self.risk_estimates = _risk_estimates(self)
|
|
271
271
|
|
|
272
272
|
end = time.perf_counter()
|
|
@@ -3,6 +3,7 @@ from ._outcome_fit import _outcome_fit as _outcome_fit
|
|
|
3
3
|
from ._risk_estimates import _risk_estimates as _risk_estimates
|
|
4
4
|
from ._subgroup_fit import _subgroup_fit as _subgroup_fit
|
|
5
5
|
from ._survival_pred import _calculate_survival as _calculate_survival
|
|
6
|
+
from ._survival_pred import _clamp as _clamp
|
|
6
7
|
from ._survival_pred import \
|
|
7
8
|
_get_outcome_predictions as _get_outcome_predictions
|
|
8
9
|
from ._survival_pred import _pred_risk as _pred_risk
|
|
@@ -370,3 +370,11 @@ def _calculate_survival(self, risk_data):
|
|
|
370
370
|
[(1 - pl.col("pred")).alias("pred"), pl.lit("survival").alias("estimate")]
|
|
371
371
|
)
|
|
372
372
|
return surv
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _clamp(data):
|
|
376
|
+
"""Clamp prediction and CI columns to [0, 1] bounds."""
|
|
377
|
+
cols = ["pred", "LCI", "UCI"]
|
|
378
|
+
exists = [c for c in cols if c in data.columns]
|
|
379
|
+
|
|
380
|
+
return data.with_columns([pl.col(col).clip(0.0, 1.0) for col in exists])
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from ._data_checker import _data_checker as _data_checker
|
|
2
2
|
from ._param_checker import _param_checker as _param_checker
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import polars as pl
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _random_selection(self):
|
|
5
|
+
"""
|
|
6
|
+
Handles the case where random selection is applied for data from
|
|
7
|
+
the __mapper -> __binder -> optionally __dynamic pipeline
|
|
8
|
+
"""
|
|
9
|
+
UIDs = (
|
|
10
|
+
self.DT.select(
|
|
11
|
+
[self.id_col, "trial", f"{self.treatment_col}{self.indicator_baseline}"]
|
|
12
|
+
)
|
|
13
|
+
.with_columns(
|
|
14
|
+
(
|
|
15
|
+
pl.col(self.id_col).cast(pl.Utf8) + "_" + pl.col("trial").cast(pl.Utf8)
|
|
16
|
+
).alias("trialID")
|
|
17
|
+
)
|
|
18
|
+
.filter(
|
|
19
|
+
pl.col(f"{self.treatment_col}{self.indicator_baseline}")
|
|
20
|
+
== self.treatment_level[0]
|
|
21
|
+
)
|
|
22
|
+
.unique("trialID")
|
|
23
|
+
.get_column("trialID")
|
|
24
|
+
.to_list()
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
NIDs = len(UIDs)
|
|
28
|
+
sample = self._rng.choice(
|
|
29
|
+
UIDs, size=int(self.selection_sample * NIDs), replace=False
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
self.DT = (
|
|
33
|
+
self.DT.with_columns(
|
|
34
|
+
(
|
|
35
|
+
pl.col(self.id_col).cast(pl.Utf8) + "_" + pl.col("trial").cast(pl.Utf8)
|
|
36
|
+
).alias("trialID")
|
|
37
|
+
)
|
|
38
|
+
.filter(
|
|
39
|
+
pl.col("trialID").is_in(sample)
|
|
40
|
+
| pl.col(f"{self.treatment_col}{self.indicator_baseline}")
|
|
41
|
+
!= self.treatment_level[0]
|
|
42
|
+
)
|
|
43
|
+
.drop("trialID")
|
|
44
|
+
)
|
|
@@ -58,13 +58,14 @@ def bootstrap_loop(method):
|
|
|
58
58
|
start = time.perf_counter()
|
|
59
59
|
|
|
60
60
|
results = []
|
|
61
|
+
original_DT = self.DT
|
|
62
|
+
|
|
61
63
|
full = method(self, *args, **kwargs)
|
|
62
64
|
results.append(full)
|
|
63
65
|
|
|
64
66
|
if getattr(self, "bootstrap_nboot") > 0 and getattr(
|
|
65
67
|
self, "_boot_samples", None
|
|
66
68
|
):
|
|
67
|
-
original_DT = self.DT
|
|
68
69
|
nboot = self.bootstrap_nboot
|
|
69
70
|
ncores = self.ncores
|
|
70
71
|
seed = getattr(self, "seed", None)
|
|
@@ -26,7 +26,7 @@ def _fit_LTFU(self, WDT):
|
|
|
26
26
|
WDT,
|
|
27
27
|
"cense_colname",
|
|
28
28
|
[self.cense_numerator, self.cense_denominator],
|
|
29
|
-
["
|
|
29
|
+
["cense_numerator_model", "cense_denominator_model"],
|
|
30
30
|
"cense_eligible_colname",
|
|
31
31
|
)
|
|
32
32
|
|
|
@@ -39,7 +39,7 @@ def _fit_visit(self, WDT):
|
|
|
39
39
|
WDT,
|
|
40
40
|
"visit_colname",
|
|
41
41
|
[self.cense_numerator, self.cense_denominator],
|
|
42
|
-
["
|
|
42
|
+
["visit_numerator_model", "visit_denominator_model"],
|
|
43
43
|
)
|
|
44
44
|
|
|
45
45
|
|
|
@@ -150,8 +150,8 @@ def _weight_predict(self, WDT):
|
|
|
150
150
|
.alias("numerator")
|
|
151
151
|
)
|
|
152
152
|
if self.cense_colname is not None:
|
|
153
|
-
p_num = _predict_model(self, self.
|
|
154
|
-
p_denom = _predict_model(self, self.
|
|
153
|
+
p_num = _predict_model(self, self.cense_numerator_model, WDT).flatten()
|
|
154
|
+
p_denom = _predict_model(self, self.cense_denominator_model, WDT).flatten()
|
|
155
155
|
WDT = WDT.with_columns(
|
|
156
156
|
[
|
|
157
157
|
pl.Series("cense_numerator", p_num),
|
|
@@ -164,8 +164,8 @@ def _weight_predict(self, WDT):
|
|
|
164
164
|
WDT = WDT.with_columns(pl.lit(1.0).alias("_cense"))
|
|
165
165
|
|
|
166
166
|
if self.visit_colname is not None:
|
|
167
|
-
p_num = _predict_model(self, self.
|
|
168
|
-
p_denom = _predict_model(self, self.
|
|
167
|
+
p_num = _predict_model(self, self.visit_numerator_model, WDT).flatten()
|
|
168
|
+
p_denom = _predict_model(self, self.visit_denominator_model, WDT).flatten()
|
|
169
169
|
|
|
170
170
|
WDT = WDT.with_columns(
|
|
171
171
|
[
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pySEQTarget
|
|
3
|
-
Version: 0.10.
|
|
3
|
+
Version: 0.10.1
|
|
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 Hernan <mhernan@hsph.harvard.edu>
|
|
6
6
|
Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>
|
|
@@ -68,8 +68,9 @@ From the user side, this amounts to creating a dataclass, `SEQopts`, and then fe
|
|
|
68
68
|
```python
|
|
69
69
|
import polars as pl
|
|
70
70
|
from pySEQTarget import SEQuential, SEQopts
|
|
71
|
+
from pySEQTarget.data import load_data
|
|
71
72
|
|
|
72
|
-
data =
|
|
73
|
+
data = load_data("SEQdata")
|
|
73
74
|
options = SEQopts(km_curves = True)
|
|
74
75
|
|
|
75
76
|
# Initiate the class
|
|
@@ -77,17 +78,18 @@ model = SEQuential(data,
|
|
|
77
78
|
id_col = "ID",
|
|
78
79
|
time_col = "time",
|
|
79
80
|
eligible_col = "eligible",
|
|
81
|
+
treatment_col = "tx_init",
|
|
82
|
+
outcome_col = "outcome",
|
|
80
83
|
time_varying_cols = ["N", "L", "P"],
|
|
81
84
|
fixed_cols = ["sex"],
|
|
82
85
|
method = "ITT",
|
|
83
|
-
|
|
86
|
+
parameters = options)
|
|
84
87
|
model.expand() # Construct the nested structure
|
|
85
88
|
model.bootstrap(bootstrap_nboot = 20) # Run 20 bootstrap samples
|
|
86
89
|
model.fit() # Fit the model
|
|
87
90
|
model.survival() # Create survival curves
|
|
88
91
|
model.plot() # Create and show a plot of the survival curves
|
|
89
92
|
model.collect() # Collection of important information
|
|
90
|
-
|
|
91
93
|
```
|
|
92
94
|
|
|
93
95
|
## Assumptions
|
|
@@ -95,4 +97,3 @@ There are several key assumptions in this package -
|
|
|
95
97
|
1. User provided `time_col` begins at 0 per unique `id_col`, we also assume this column contains only integers and continues by 1 for every time step, e.g. (0, 1, 2, 3, 4, ...) is allowed and (0, 1, 2, 2.5, ...) or (0, 1, 4, 5) are not
|
|
96
98
|
1. Provided `time_col` entries may be out of order at intake as a sort is enforced at expansion.
|
|
97
99
|
2. `eligible_col` and elements of `excused_colnames` are once 1, only 1 (with respect to `time_col`) flag variables.
|
|
98
|
-
|
|
@@ -18,7 +18,7 @@ pySEQTarget/analysis/_subgroup_fit.py
|
|
|
18
18
|
pySEQTarget/analysis/_survival_pred.py
|
|
19
19
|
pySEQTarget/data/__init__.py
|
|
20
20
|
pySEQTarget/error/__init__.py
|
|
21
|
-
pySEQTarget/error/
|
|
21
|
+
pySEQTarget/error/_data_checker.py
|
|
22
22
|
pySEQTarget/error/_param_checker.py
|
|
23
23
|
pySEQTarget/expansion/__init__.py
|
|
24
24
|
pySEQTarget/expansion/_binder.py
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import polars as pl
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def _random_selection(self):
|
|
5
|
-
"""
|
|
6
|
-
Handles the case where random selection is applied for data from
|
|
7
|
-
the __mapper -> __binder -> optionally __dynamic pipeline
|
|
8
|
-
"""
|
|
9
|
-
UIDs = (
|
|
10
|
-
self.DT.select(
|
|
11
|
-
[self.id_col, "trial", f"{self.treatment_col}{self.indicator_baseline}"]
|
|
12
|
-
)
|
|
13
|
-
.with_columns((pl.col(self.id_col) + "_" + pl.col("trial")).alias("trialID"))
|
|
14
|
-
.filter(pl.col(f"{self.treatment_col}{self.indicator_baseline}") == 0)
|
|
15
|
-
.unique("trialID")
|
|
16
|
-
.to_series()
|
|
17
|
-
.to_list()
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
NIDs = len(UIDs)
|
|
21
|
-
sample = self._rng.choice(
|
|
22
|
-
UIDs, size=int(self.selection_sample * NIDs), replace=False
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
self.DT = (
|
|
26
|
-
self.DT.with_columns(
|
|
27
|
-
(pl.col(self.id_col) + "_" + pl.col("trial")).alias("trialID")
|
|
28
|
-
)
|
|
29
|
-
.filter(pl.col("trialID").is_in(sample))
|
|
30
|
-
.drop("trialID")
|
|
31
|
-
)
|
|
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
|