CompetingRiskForest

A random survival forest for competing risks with native CIF-based splitting.

Usage

Source

CompetingRiskForest(
    *,
    n_estimators=100,
    max_depth=None,
    min_samples_split=6,
    min_samples_leaf=3,
    max_features="sqrt",
    bootstrap=True,
    oob_score=False,
    random_state=None,
)

Grows an ensemble of trees that partition subjects using the log-rank CR statistic. At each candidate split, the at-risk set follows the subdistribution convention: subjects who experienced a competing event remain at risk, so the split directly targets separation of the cumulative incidence functions. Each leaf estimates per-cause CIF via the Aalen-Johansen estimator, and the forest averages these curves across all trees.

Parameters

n_estimators: int = 100

Number of trees in the forest.

max_depth: int | None = None

Maximum depth of each tree (None for unlimited).

min_samples_split: int = 6

Minimum node size eligible for splitting.

min_samples_leaf: int = 3

Minimum subjects in each child of a split.

max_features: Any = "sqrt"

Covariates considered per split: "sqrt" (default), "log2", an int, a float, or None.

bootstrap: bool = True

Whether to grow each tree on a bootstrap sample. Required for oob_score and variable_importance.

oob_score: bool = False

Whether to compute an out-of-bag concordance estimate after fitting.

random_state: Any = None
Seed or numpy.random.Generator for reproducibility.

Examples

import greenwood as gw

mg = gw.load_dataset("mgus2")

# The first of progression (PCM) or death, from each endpoint's time and status columns
pcm_or_death = gw.Outcome.first_event(
    endpoints={"pcm": ("ptime", "pstat"), "death": ("futime", "death")}
)

crf = gw.CompetingRiskForest(n_estimators=50, random_state=0).fit(
    pcm_or_death, covariates=["age", "sex"], data=mg
)
crf
CompetingRiskForest (50 logrankCR trees, max_features='sqrt')
n = 1384, events = 975, features = 2
causes: pcm, death

Methods

Name Description
fit() Fit the competing-risk forest.
predict() Predict cumulative incidence functions from the forest.
predict_risk() Scalar risk score: summed CIF over the event-time grid for each subject.
variable_importance() Permutation variable importance on out-of-bag samples.

fit()

Fit the competing-risk forest.

Usage

Source

fit(
    surv,
    covariates=None,
    *,
    data=None,
)

Parameters

surv: Surv | Outcome | str

A multi-state Surv response, built with gw.Surv() and a categorical event. An Outcome or a formula string such as "Surv(time, factor(cause, c(0, 1, 2), c('censor', 'pcm', 'death'))) ~ age" is also accepted, with its columns read from data. The right-hand side sets covariates.

covariates: Any = None

A dataframe, a 2-D array, or a formula string evaluated against data. A list of column names in data also works.

data: Any = None
A data frame (pandas, Polars, PyArrow, DuckDB, a lazy frame, …) holding the columns named by the response and covariates. When surv is an Outcome or a formula, rows with a missing value in any column used are dropped before fitting. Covariate formula strings and lists of column names are also resolved here.

Returns

self
The fitted estimator with attributes trees_, event_times_, states_, cause_codes_, and oob_score_.

Examples

Fit a competing-risk forest on the mgus2 dataset. The response has two causes (plasma-cell malignancy and death) and the model learns per-cause CIF curves:

import greenwood as gw

mg = gw.load_dataset("mgus2")
pcm_or_death = gw.Outcome.first_event(
    endpoints={"pcm": ("ptime", "pstat"), "death": ("futime", "death")}
)

crf = gw.CompetingRiskForest(
    n_estimators=50, oob_score=True, random_state=0
).fit(pcm_or_death, covariates=["age", "sex"], data=mg)
crf
CompetingRiskForest (50 logrankCR trees, max_features='sqrt')
n = 1384, events = 975, features = 2
causes: pcm, death
out-of-bag concordance = 0.4669

predict()

Predict cumulative incidence functions from the forest.

Usage

Source

predict(
    newdata=None,
    *,
    cause=None,
    times=None,
    format=None,
)

Returns a DataFrame with a time column and one column per subject, containing the ensemble-averaged CIF F_k(t \mid x) for the requested cause. If cause is None and there is only one cause, that cause is used; otherwise cause is required.

Parameters

newdata: Any = None

Covariates to predict for. A data frame may also hold other columns. The covariates are picked out by name and coded as they were at fit time, so the frame the model was fit on can be passed as is.

cause: int | str | None = None

Which cause to predict. A string label or integer code. Required when there are multiple causes.

times: Any = None

Times at which to evaluate the CIF. Defaults to the training event times.

format: str | None = None
DataFrame backend for the returned table.

Returns

DataFrame
Columns time, subject_1, subject_2, …

predict_risk()

Scalar risk score: summed CIF over the event-time grid for each subject.

Usage

Source

predict_risk(
    newdata=None,
    *,
    cause=None,
)

Higher values indicate higher predicted cumulative incidence for the given cause.


variable_importance()

Permutation variable importance on out-of-bag samples.

Usage

Source

variable_importance(
    *,
    cause=None,
    n_repeats=5,
    random_state=None,
    format=None,
)

For each covariate, its values are randomly permuted and the increase in OOB prediction error (1 - concordance) is measured.

Parameters

cause: int | str | None = None

Which cause to compute importance for. Defaults to the first cause.

n_repeats: int = 5

Number of random permutations per covariate.

random_state: Any = None

Seed or generator controlling permutations.

format: str | None = None
DataFrame backend for the returned table.

Returns

DataFrame
One row per covariate with columns term and importance.