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, visits, id="id", time="time", event="event", visit_time="day"
)
y = gw.Surv.counting(long["tstart"], long["tstop"], long["event"])
cox = gw.CoxPH().fit(y, long[["bili"]])split_episodes()
Convert repeated-measurement data into counting-process (episode-split) format.
Usage
split_episodes(
baseline,
visits,
*,
id,
time,
event,
visit_time,
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 Surv.counting() 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.
Parameters
baseline: Any-
One row per subject. Must contain the
id,time, and event columns. Any additional columns are treated as time-fixed covariates and carried through to every output row for that subject. visits: Any-
One row per (subject, visit). Must contain the
idandvisit_timecolumns. Every other column is treated as a time-varying covariate. 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. 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 toSurv.counting(tstart, tstop, event)and CoxPH.fit().
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: