IPCW concordance index for cause-specific cumulative incidence.
concordance_index_incidence(
surv,
incidence_prob,
*,
data=None,
cause,
tau=None,
)
Measures how well predicted cumulative incidence probabilities for a specific cause discriminate between subjects who experience that cause and those who do not. This extends the IPCW concordance to competing risks by considering two types of comparable pairs: standard pairs (event-of-interest vs. still-at-risk) and competing-event pairs (event-of-interest vs. competing event).
Interpretation:
- 0.5: Random discrimination (predicted CIF carries no information about cause ordering).
0.5: Better-than-random. Subjects who experience the cause tend to have higher predicted CIF.
- 1.0: Perfect discrimination.
Parameters
surv: Surv | Outcome | str
-
A multi-state Surv response (from gw.Surv() with a categorical event). An Outcome or a formula response such as 'Surv(time, status == 2)' is also accepted, with its columns read from data.
incidence_prob: Any
-
Predicted cumulative incidence probability for the cause of interest at the evaluation time tau, one value per subject. Higher values should indicate a higher predicted probability of experiencing the cause. Accepts a 1-D array, Pandas/Polars Series, or Python sequence.
cause: int
-
The cause of interest, as an integer event code from the Surv response.
tau: float | None = None
-
Truncation time. Only subjects with events before tau contribute as cases. Defaults to the largest observed time for the cause of interest.
data: Any = None
-
A data frame (pandas, Polars, PyArrow, DuckDB, a lazy frame, …) holding the columns named by the response and
incidence_prob. When surv is an Outcome or a formula, rows with a missing value in any column used are dropped first, along with the matching rows of any arrays passed alongside.
Returns
float
-
Concordance index between 0 and 1.
Details
Two types of comparable pairs contribute to the concordance:
- Type A (standard survival pairs): Subject i experienced cause k at T_i, and subject j is still at risk at T_i (T_j > T_i). Weighted by 1 / \hat{G}(T_i)^2.
- Type B (competing-event pairs): Subject i experienced cause k at T_i, and subject j experienced a competing event at T_j \le T_i. Weighted by 1 / (\hat{G}(T_i) \cdot \hat{G}(T_j)).
A pair is concordant if the subject with the cause of interest has a higher predicted CIF than the comparator. IPCW weights correct for censoring bias by reweighting pairs according to the inverse censoring probability.
Examples
Name the competing endpoints in the mgus2 dataset and evaluate the concordance of a marginal Aalen-Johansen CIF as a naive baseline:
import greenwood as gw
import numpy as np
# The first of progression (PCM) or death, each with its own time and status columns
mgus2 = gw.load_dataset("mgus2", backend="polars")
first = gw.Outcome.first_event(
endpoints={"pcm": ("ptime", "pstat"), "death": ("futime", "death")}
)
# Fit Aalen-Johansen for the marginal CIF
aj = gw.AalenJohansen().fit(first, data=mgus2)
cif_df = aj.to_frame(format="polars")
pcm_cif = cif_df.filter(cif_df["cause"] == "pcm")
# Marginal CIF at tau=240 months as a naive predictor (same value for everyone)
tau = 240.0
marginal_at_tau = float(
np.interp(tau, pcm_cif["time"].to_numpy(), pcm_cif["estimate"].to_numpy())
)
pred = np.full(mgus2.height, marginal_at_tau)
c = gw.concordance_index_incidence(
first, incidence_prob=pred, cause=1, tau=tau, data=mgus2
)
c
np.float64(0.49999999999999994)