# CompetingRiskForest


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


Usage

``` python
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


``` python
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) | Fit the competing-risk forest. |
| [predict()](#predict) | Predict cumulative incidence functions from the forest. |
| [predict_risk()](#predict_risk) | Scalar risk score: summed CIF over the event-time grid for each subject. |
| [variable_importance()](#variable_importance) | Permutation variable importance on out-of-bag samples. |

------------------------------------------------------------------------


### fit()


Fit the competing-risk forest.


Usage

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


#### Parameters


`surv: Surv | Outcome | str`  
A multi-state [Surv](Surv.md#greenwood.Surv) response, built with `gw.Surv()` and a categorical `event`. An [Outcome](Outcome.md#greenwood.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](Outcome.md#greenwood.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:


``` python
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

``` python
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

``` python
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

``` python
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`.
