import pandas as pd
import greenwood as gw
baseline = pd.DataFrame({
"id": [1, 2, 3],
"time": [10.0, 8.0, 12.0],
"event": [1, 0, 1],
})
visits = pd.DataFrame({
"id": [1, 1, 2, 3, 3, 3],
"day": [0.0, 5.0, 0.0, 0.0, 4.0, 8.0],
"bili": [1.2, 2.4, 0.8, 3.1, 2.9, 4.0],
})
long = gw.split_episodes(
baseline=baseline, visits=visits, id="id", time="time", event="event", visit_time="day"
)
cox = gw.CoxPH().fit("Surv(tstart, tstop, event) ~ bili", data=long)split_episodes()
Convert repeated-measurement data into counting-process (episode-split) format.
Usage
split_episodes(
baseline,
visits,
*,
id,
time,
event,
visit_time,
covariates=None,
baseline_covariates=None,
carry_forward=True,
format=None,
)Takes a subject-level baseline table and a long-format visits table, and merges them into the interval-per-row counting-process layout required by a counting-process response ("Surv(tstart, tstop, event)") and CoxPH. Each row in the output represents a constant-covariate interval (tstart, tstop] for one subject.
The covariate value measured at visit time v applies to the interval [v, next_v). The event indicator is 1 only on the final interval for subjects who experienced the event; all earlier intervals carry 0. A visit at the follow-up end does not create a new interval: the interval ending there retains the event and the covariate value measured before the endpoint.
Parameters
baseline: Any-
The subject-level table. Must contain the
id,time, andeventcolumns. It may have one row per subject, or it may be the same long table asvisitswhen that table repeats the follow-up time and event on every row. In that case the first row of each subject is used, after checking thattime,event, and anybaseline_covariatesare constant within the subject. visits: Any-
One row per (subject, visit). Must contain the
idandvisit_timecolumns. id: str-
Column name linking
baselineandvisits. time: str-
Column in
baselinegiving the end of follow-up (right-censored exit time). event: str-
Column in
baselinegiving the event indicator. visit_time: str-
Column in
visitsgiving the measurement time for each row. covariates: Sequence[str] | None = None-
The columns of
visitsto carry as time-varying covariates. The default (None) uses every column other thanidandvisit_time. baseline_covariates: Sequence[str] | None = None-
The columns of
baselineto carry as time-fixed covariates. The default (None) uses every column other thanid,time, andeventwhenbaselinehas one row per subject, and none when it repeats subjects (a long table usually holds per-visit columns that are not fixed in time). carry_forward: bool = True-
If
True(default), the last observed covariate value is carried forward to the end of follow-up (LOCF), producing a final interval(last_visit, time]. IfFalse, follow-up is truncated at the last visit; the trailing interval is dropped and the subject is effectively administratively censored there. format: str | None = None-
Output format:
None(default),"pandas","polars", or"pyarrow".None(default): auto-detect, trying Polars first, then Pandas, then PyArrow."pandas": return apandas.DataFrame."polars": return apolars.DataFrame."pyarrow": return apyarrow.Table.
Returns
pandas.DataFrame, polars.DataFrame, or pyarrow.Table-
Counting-process dataset with columns
(id, tstart, tstop, event, [time-fixed covariates], [time-varying covariates]). Ready to pass directly to CoxPH.fit() with a formula such as"Surv(tstart, tstop, event) ~ bili".
Raises
ValueError- If required columns are missing, if any visit time exceeds the subject’s follow-up end, or if the resulting dataset is empty.
Examples
Build a minimal TVC dataset and fit a Cox model: