# CauseSpecificCox


Cause-specific Cox proportional-hazards model for competing risks.


Usage

``` python
CauseSpecificCox(
    cause,
    *,
    ties="efron",
    conf_level=0.95,
)
```


In a competing-risks setting, a cause-specific hazard model answers "among subjects still event-free, what drives the rate of this particular event?" It does so by treating competing events as censoring: subjects who experience a different cause are removed from the risk set at the time of their competing event, and a standard Cox model is fitted on the re-coded data.

This wrapper takes a multi-state [Surv](Surv.md#greenwood.Surv) response and a target cause, automatically re-codes the competing events as censored, and delegates to [CoxPH](CoxPH.md#greenwood.CoxPH). All [CoxPH](CoxPH.md#greenwood.CoxPH) features (stratification, frailty, robust standard errors, diagnostics, prediction) are available on the fitted object.


## Parameters


`cause: Any`  
The cause of interest. Can be a state label (string) matching one of the [states](Surv.md#greenwood.Surv.states) in the [Surv](Surv.md#greenwood.Surv) response, or an integer cause code (1-indexed).

`ties: str = ``"efron"`  
Tie-handling method passed to [CoxPH](CoxPH.md#greenwood.CoxPH): `"efron"` (default) or `"breslow"`.

`conf_level: float = ``0.95`  
Confidence level for coefficient intervals (default 0.95).


## Examples

Fit a cause-specific Cox model for PCM progression in the `mgus2` dataset:


``` python
import greenwood as gw

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

csc = gw.CauseSpecificCox(cause="pcm").fit(cr, covariates=["age", "sex"], data=mg)
csc
```


    CauseSpecificCox (cause-specific Cox model, cause='pcm', ties='efron')

              coef  exp(coef)  se(coef)       z       p
    age    0.01304      1.013  0.008259   1.579  0.1144
    sexM  -0.02514     0.9752    0.1885  -0.133  0.8939

    n = 1384, events = 115
    Likelihood ratio test = 2.682 on 2 df, p = 0.2616


Compare cause-specific hazard ratios for both causes side by side:


``` python
csc_death = gw.CauseSpecificCox(cause="death").fit(cr, covariates=["age", "sex"], data=mg)
gw.tidy(csc, exponentiate=True, format="polars")
```


shape: (2, 7)

| term   | estimate | std_error | statistic | p_value  | conf_low | conf_high |
|--------|----------|-----------|-----------|----------|----------|-----------|
| str    | f64      | f64       | f64       | f64      | f64      | f64       |
| "age"  | 1.013124 | 0.008259  | 1.578771  | 0.114389 | 0.996857 | 1.029657  |
| "sexM" | 0.975176 | 0.188456  | -0.133388 | 0.893886 | 0.674014 | 1.410902  |


## Methods

| Name | Description |
|----|----|
| [fit()](#fit) | Fit the cause-specific Cox model. |

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


### fit()


Fit the cause-specific Cox model.


Usage

``` python
fit(
    surv,
    covariates=None,
    *,
    data=None,
    strata=None,
    robust=False,
    cluster=None,
    frailty=None,
    frailty_cluster=None,
    frailty_theta=0.5,
    frailty_max_iter=30,
    max_iter=30,
    tol=1e-09,
    weights=None,
)
```


Re-codes the multi-state response so that the target cause is treated as the event and all competing causes are treated as censored, then fits a standard [CoxPH](CoxPH.md#greenwood.CoxPH) model on the re-coded data.


#### Parameters


`surv: Surv | Outcome | str`  
A multi-state response: a [Surv](Surv.md#greenwood.Surv) with a categorical event, an [Outcome](Outcome.md#greenwood.Outcome) (such as `gw.Outcome.first_event(...)`), or a formula string such as `"Surv(etime, factor(cause, c(0, 1, 2), c('censor', 'pcm', 'death'))) ~ age + sex"`. An [Outcome](Outcome.md#greenwood.Outcome) or formula reads its columns from `data`. The formula's right-hand side sets `covariates`.

`covariates: Any = None`  
A dataframe or 2-D array of covariates. 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, `strata`, `cluster`, `frailty_cluster`, 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.

`strata: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`robust: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`cluster: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`frailty: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`frailty_cluster: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`frailty_theta: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`frailty_max_iter: Any = None`  
Passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`max_iter: int = ``30`  
Newton-Raphson iteration control passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`tol: int = ``30`  
Newton-Raphson iteration control passed through to [CoxPH.fit()](CoxPH.md#greenwood.CoxPH.fit).

`weights: Any = None`  
Case weights, one per row (a column name in `data`, or an array). Must be finite and strictly positive. Default is `None` (all weights `1`).


#### Returns


`CauseSpecificCox`  
The fitted estimator.


#### Examples

Fit a cause-specific Cox model for plasma-cell malignancy (pcm) in the `mgus2` dataset. Competing events (death) are treated as censored:


``` python
import greenwood as gw

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

csc = gw.CauseSpecificCox(cause="pcm").fit(
    cr, covariates=["age", "sex"], data=mg
)
csc
```


    CauseSpecificCox (cause-specific Cox model, cause='pcm', ties='efron')

              coef  exp(coef)  se(coef)       z       p
    age    0.01304      1.013  0.008259   1.579  0.1144
    sexM  -0.02514     0.9752    0.1885  -0.133  0.8939

    n = 1384, events = 115
    Likelihood ratio test = 2.682 on 2 df, p = 0.2616


Exponentiated coefficients give cause-specific hazard ratios:


``` python
gw.tidy(csc, exponentiate=True, format="polars")
```


shape: (2, 7)

| term   | estimate | std_error | statistic | p_value  | conf_low | conf_high |
|--------|----------|-----------|-----------|----------|----------|-----------|
| str    | f64      | f64       | f64       | f64      | f64      | f64       |
| "age"  | 1.013124 | 0.008259  | 1.578771  | 0.114389 | 0.996857 | 1.029657  |
| "sexM" | 0.975176 | 0.188456  | -0.133388 | 0.893886 | 0.674014 | 1.410902  |
