## NelsonAalen


Nelson-Aalen estimator of the cumulative hazard.


Usage

``` python
NelsonAalen(
    *,
    conf_type="log",
    conf_level=0.95,
)
```


The Nelson-Aalen estimator provides a non-parametric estimate of the cumulative hazard function, which represents the total "accumulated risk" up to a given time. Unlike the Kaplan-Meier estimator which models survival directly, this approach models the force of mortality. The cumulative hazard at each event time is computed as a running sum of the ratio of events to subjects at risk:

\\ H(t) = \sum\_{t_i \le t} \frac{d_i}{n_i} \\

This estimator is useful when you want to examine the hazard directly rather than survival probabilities, and is often used as the basis for other analyses. You can convert the cumulative hazard to a survival estimate via \\S(t) = \exp(-H(t))\\, though the Kaplan-Meier estimator is typically preferred for direct survival estimation. Call [fit()](AFT.md#greenwood.AFT.fit) with a right-censored [Surv](Surv.md#greenwood.Surv) response to compute cumulative hazard at each event time.

The variance of the cumulative hazard estimate uses Aalen's formula:

\\ \mathrm{Var}(H(t)) = \sum\_{t_i \le t} \frac{d_i}{n_i^2} \\

Confidence intervals can be constructed on the plain or log scale, with the log scale providing better coverage in the tails.


## Parameters


`conf_type: str = ``"log"`  
Confidence-interval transform: `"plain"` (default for Nelson-Aalen) or `"log"`.

`conf_level: float = ``0.95`  
Confidence level for the interval (default 0.95).


## Returns


`Fitted estimator`  
Call [fit()](AFT.md#greenwood.AFT.fit) to produce a fitted estimator with cached results (`time_`, `cumulative_hazard_`, `std_error_`, `conf_low_`, `conf_high_`, `n_risk_`, `n_event_`, `n_censor_`), accessible as aligned arrays or exported to DataFrames.


## Details

Call [fit()](AFT.md#greenwood.AFT.fit) with a [Surv](Surv.md#greenwood.Surv) response. Results are exposed as aligned arrays, as tidy frames via [to_frame()](AFT.md#greenwood.AFT.to_frame) (optionally `format=`), and through the [predict()](AFT.md#greenwood.AFT.predict), [quantile()](KaplanMeier.md#greenwood.KaplanMeier.quantile), and other methods.


## Examples

Build a [Surv](Surv.md#greenwood.Surv) response from the bundled `lung` dataset and fit the estimator. Printing the fitted object reports the counts and the maximum cumulative hazard reached.


``` python
import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
na = gw.NelsonAalen().fit(y)
na
```


    NelsonAalen (Nelson-Aalen cumulative hazard estimate)

        n  events  max cumhaz
      228     165       2.889


## Methods

| Name | Description |
|----|----|
| [fit()](#fit) | Fit the Nelson-Aalen estimator to survival data. |
| [to_frame()](#to_frame) | Return the fitted cumulative hazard as a DataFrame. |

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


#### fit()


Fit the Nelson-Aalen estimator to survival data.


Usage

``` python
fit(surv, *, by=None, weights=None)
```


Computes the cumulative hazard function \\H(t)\\ from a [Surv](Surv.md#greenwood.Surv) response (time-to-event data). Like Kaplan-Meier, this is a non-parametric estimate requiring no distributional assumptions. The Nelson-Aalen estimator is an alternative to Kaplan-Meier; it estimates the cumulative hazard directly (sum of \\d/n\\ at each event time), from which the survival probability can be derived via \\S(t) = \exp(-H(t))\\. Results are stored in the fitted object; access them via attributes or export to a DataFrame with [to_frame()](AFT.md#greenwood.AFT.to_frame) (optionally `format=`).

Pass `by=` to produce separate cumulative hazard curves per group (stratified analysis), enabling covariate-free comparison of hazard accumulation across groups. Optionally supply `weights` to adjust for selection bias or survey design.


##### Parameters


`surv: Surv`  
A [Surv](Surv.md#greenwood.Surv) response (typically right-censored). Built from data using [Surv.right()](Surv.md#greenwood.Surv.right), [Surv.interval()](Surv.md#greenwood.Surv.interval), etc.

`by: Any = None`  
Optional grouping variable (e.g., a column or array). Produces one fit (one cumulative hazard curve) per unique value of `by`, enabling stratified Nelson-Aalen analysis. Default (`None`): fit a single, unstratified curve.

`weights: Any = None`  
Optional weights (e.g., from survey design or inverse-probability-of-censoring adjustments). Must have the same length as `surv`. Default (`None`): unit weights.


##### Returns


`NelsonAalen`  
The fitted estimator object itself (for method chaining) with cached results (`time_`, `cumulative_hazard_`, `conf_low_`, `conf_high_`, `n_risk_`, `n_event_` as attributes).


##### Details

The Nelson-Aalen estimator is

\\ H(t) = \sum\_{t_i \le t} \frac{d_i}{n_i} \\

where \\d_i\\ and \\n_i\\ are events and number at risk at time \\t_i\\. Its variance is estimated using Aalen's formula:

\\ \mathrm{Var}(H) = \sum \frac{d_i}{n_i^2} \\

The survival function can be recovered as \\S(t) = \exp(-H(t))\\. Confidence intervals are point-wise.


##### Examples

Fit a single (unstratified) cumulative hazard curve on the bundled `lung` dataset:


``` python
import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
na = gw.NelsonAalen().fit(y)
na
```


    NelsonAalen (Nelson-Aalen cumulative hazard estimate)

        n  events  max cumhaz
      228     165       2.889


Fit stratified curves by sex to compare cumulative hazard accumulation:


``` python
na_stratified = gw.NelsonAalen().fit(y, by=lung["sex"])
na_stratified
```


    NelsonAalen (Nelson-Aalen cumulative hazard estimate)

         n  events  max cumhaz
    1  138     112       3.163
    2   90      53       2.322


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


#### to_frame()


Return the fitted cumulative hazard as a DataFrame.


Usage

``` python
to_frame(*, format=None)
```


Exports the Nelson-Aalen estimate with one row per event time, including risk-set counts, the cumulative hazard estimate, its standard error, confidence limits, and optional strata labels.


##### Parameters


`format: str | None = None`  
Output format: `None` (default), `"pandas"`, `"polars"`, or `"pyarrow"`. When `None`, a backend is auto-detected (Polars, then Pandas, then PyArrow).


##### Returns


`pandas.DataFrame, polars.DataFrame, or pyarrow.Table`  
A tidy table with columns `time`, `n_risk`, `n_event`, `estimate`, `std_error`, `conf_low`, `conf_high`, and optionally `strata`.


##### Raises


`ImportError`  
If the requested (or, when auto-detecting, any) DataFrame library is not installed.


##### Examples

Fit a Nelson-Aalen estimator on the bundled `lung` dataset, then export the fitted cumulative-hazard curve as a Polars frame:


``` python
import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
na = gw.NelsonAalen().fit(y)
na.to_frame(format="polars")
```


shape: (186, 7)

| time   | n_risk | n_event | estimate | std_error | conf_low | conf_high |
|--------|--------|---------|----------|-----------|----------|-----------|
| f64    | f64    | f64     | f64      | f64       | f64      | f64       |
| 5.0    | 228.0  | 1.0     | 0.004386 | 0.004386  | 0.000618 | 0.031136  |
| 11.0   | 227.0  | 3.0     | 0.017602 | 0.008801  | 0.006606 | 0.046899  |
| 12.0   | 224.0  | 1.0     | 0.022066 | 0.009868  | 0.009184 | 0.053015  |
| 13.0   | 223.0  | 2.0     | 0.031035 | 0.01173   | 0.014795 | 0.065101  |
| 15.0   | 221.0  | 1.0     | 0.03556  | 0.012573  | 0.017783 | 0.071108  |
| …      | …      | …       | …        | …         | …        | …         |
| 840.0  | 5.0    | 0.0     | 2.639267 | 0.335859  | 2.056667 | 3.386903  |
| 883.0  | 4.0    | 1.0     | 2.889267 | 0.41869   | 2.174895 | 3.838285  |
| 965.0  | 3.0    | 0.0     | 2.889267 | 0.41869   | 2.174895 | 3.838285  |
| 1010.0 | 2.0    | 0.0     | 2.889267 | 0.41869   | 2.174895 | 3.838285  |
| 1022.0 | 1.0    | 0.0     | 2.889267 | 0.41869   | 2.174895 | 3.838285  |


Pass a different `format=` for pandas or PyArrow output:


``` python
na.to_frame(format="pandas")
```


|     | time   | n_risk | n_event | estimate | std_error | conf_low | conf_high |
|-----|--------|--------|---------|----------|-----------|----------|-----------|
| 0   | 5.0    | 228.0  | 1.0     | 0.004386 | 0.004386  | 0.000618 | 0.031136  |
| 1   | 11.0   | 227.0  | 3.0     | 0.017602 | 0.008801  | 0.006606 | 0.046899  |
| 2   | 12.0   | 224.0  | 1.0     | 0.022066 | 0.009868  | 0.009184 | 0.053015  |
| 3   | 13.0   | 223.0  | 2.0     | 0.031035 | 0.011730  | 0.014795 | 0.065101  |
| 4   | 15.0   | 221.0  | 1.0     | 0.035560 | 0.012573  | 0.017783 | 0.071108  |
| ... | ...    | ...    | ...     | ...      | ...       | ...      | ...       |
| 181 | 840.0  | 5.0    | 0.0     | 2.639267 | 0.335859  | 2.056667 | 3.386903  |
| 182 | 883.0  | 4.0    | 1.0     | 2.889267 | 0.418690  | 2.174895 | 3.838285  |
| 183 | 965.0  | 3.0    | 0.0     | 2.889267 | 0.418690  | 2.174895 | 3.838285  |
| 184 | 1010.0 | 2.0    | 0.0     | 2.889267 | 0.418690  | 2.174895 | 3.838285  |
| 185 | 1022.0 | 1.0    | 0.0     | 2.889267 | 0.418690  | 2.174895 | 3.838285  |

186 rows × 7 columns
