A random survival forest for competing risks with native CIF-based splitting.
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.
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.
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.
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.
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.