first_event()

Build a competing-risks response from several endpoints: the earliest observed event wins.

Usage

Source

first_event(
    endpoints,
    *,
    censor_at=None,
    start=None,
)

Some datasets record each endpoint in its own pair of columns rather than in one outcome column. mgus2 is an example: ptime/pstat hold the time to plasma cell malignancy (PCM) and whether it occurred, and futime/death do the same for death. A competing-risks analysis needs one time and one cause per subject: the first endpoint observed, or censoring if none was.

For each row, the endpoint with the earliest observed event becomes the cause and its time becomes the event time. Ties go to the endpoint listed first. Rows with no observed event are censored at the latest endpoint time (the last time the subject was known to be event-free), or at censor_at if given. This helper is Greenwood’s own: R’s survival has no direct equivalent.

Parameters

endpoints: Mapping[str, tuple[Any, Any]]

A mapping of state name to a (time, event) pair, in priority order for ties. event is logical or 0/1.

censor_at: Any = None

The time at which rows with no observed event are censored. The default is the latest of the endpoint times.

start: Any = None
Entry times for late entry. When given, the result is a multi-state counting-process response.

Returns

Surv
A multi-state response whose states are the endpoint names, in order.

Warns

UserWarning
When a row’s event is recorded after another endpoint’s follow-up had already ended without an event. This often means the time columns don’t share an origin or a unit.

Examples

Two endpoints for three subjects. Subject 1 has endpoint "a" at time 5, subject 2 has "b" at time 8, and subject 3 is censored at time 9:

import greenwood as gw

gw.first_event(
    endpoints={
        "a": ([5.0, 9.0, 4.0], [1, 0, 0]),
        "b": ([7.0, 8.0, 9.0], [0, 1, 0]),
    }
)
Surv(type=mright, n=3, events=2, states=('a', 'b'))

For a data frame such as the bundled mgus2 (one column pair per endpoint), name the columns with Outcome.first_event() and pass data= when fitting. PCM is listed first, so a PCM diagnosed at the same time as death counts as PCM:

mgus2 = gw.load_dataset("mgus2")

cr = gw.Outcome.first_event(endpoints={"pcm": ("ptime", "pstat"), "death": ("futime", "death")})
gw.AalenJohansen().fit(cr, data=mgus2)
AalenJohansen (Aalen-Johansen cumulative incidence)

states: pcm, death
n = 1384

       final CIF
pcm       0.1613
death     0.8387