Modern survival analysis for Python: Narwhals-native, R-validated, beautifully visualized.

AI / Agents

Skills
llms.txt
llms-full.txt

Developers

Richard Iannone

Maintainer

Community

Contributing guide
Code of conduct
Project roadmap
Security policy
Full license MIT
Citing greenwood

Meta

Requires: Python >=3.10
Provides-Extra: pd, pl, pa, formula, plotnine, altair, tables, fast, all, dev, docs
Package Info

Modern survival analysis for Python

Greenwood turns time-to-event data into estimates, tests, models, and figures. Whether you’re tracking patient outcomes, equipment failure times, or any event that takes time to happen, Greenwood provides a complete, production-ready toolkit for survival analysis.

Unlike many statistical libraries, Greenwood is built on Narwhals for backend-agnostic compute, validated to tolerance against R’s gold-standard survival package, and visualized with publication-quality interactive plots and tables. It works with Pandas, Polars, PyArrow, or any dataframe library you prefer.

Why Greenwood?

  • Works with your dataframe library: Pandas, Polars, PyArrow, or any Narwhals-compatible frame (use the format= argument to control output types).
  • Rigorously validated: every statistic is tested to tolerance against R’s survival package, so results match what the field already trusts.
  • Beautiful visualizations: interactive survival curves, forest plots, and cumulative incidence plots with a choice of plotting backends.
  • Publication-ready tables: built-in integration with Great Tables for production-quality reporting.
  • Complete toolkit: from simple Kaplan-Meier curves to Cox regression, competing risks, and multi-state models (everything you need, all validated)`.

The analytical pipeline

Every Greenwood analysis follows a consistent workflow:

  1. Represent the data with Surv: capture survival outcomes and censoring (right, left, interval, or counting-process form) in a validated response object.
  2. Estimate and summarize: use KaplanMeier or NelsonAalen to describe the data, then compare groups with logrank_test, trend tests, or RMST comparisons.
  3. Build and fit models: fit Cox proportional hazards, parametric AFT models, or competing-risks models to examine covariate effects.
  4. Visualize and evaluate: create publication-quality plots with plot_survival, forest_plot, or cif_plot, and assess model performance with concordance, Brier scores, or cross-validation.
  5. Report results: tidy model summaries and publication tables are built in via broom-compatible tidy() functions and Great Tables.

A first look

Here’s a complete example: load survival data, estimate a curve, test for differences, and visualize.

Step 1: Represent the data with a Surv object

import greenwood as gw

# Load data and represent it as a survival object
lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
y
Surv(type=right, n=228, events=165)

Step 2: Estimate Kaplan-Meier survival curves, stratified by sex

# Fit stratified Kaplan-Meier with log-log confidence intervals
km = gw.KaplanMeier(conf_type="log-log").fit(y, by=lung["sex"])

# Get median survival per group with 95% confidence intervals
km.median(ci=True)
{1: (270.0, 210.0, 306.0), 2: (426.0, 345.0, 524.0)}

Step 3: Compare survival between groups with a log-rank test

# Test for differences in survival between sexes
test_result = gw.logrank_test(y, group=lung["sex"])
test_result
TestResult(method='Log-rank test', statistic=10.3267, df=1, p_value=0.001311)

Step 4: Visualize with an interactive plot and at-risk table

# Create publication-quality survival curves
gw.plot_survival(km, risk_table=True)

Step 5: Fit a Cox proportional hazards model

# Model covariate effects on hazard
cox = gw.CoxPH().fit(y, lung[["age", "sex"]])

# Get hazard ratios with confidence intervals
gw.tidy(cox, exponentiate=True, format="polars")
shape: (2, 7)
termestimatestd_errorstatisticp_valueconf_lowconf_high
strf64f64f64f64f64f64
"age"1.0171910.0092231.8480780.0645910.9989691.035747
"sex"0.5985660.167458-3.064760.0021780.4310940.831099

What’s inside

Descriptive statistics: Kaplan-Meier curves with Greenwood confidence intervals, restricted mean survival time (RMST), quantiles, and medians. Nelson-Aalen cumulative hazard. Event tables and risk sets.

Group comparisons: Log-rank and Peto-Peto tests, Fleming-Harrington tests for weighted comparisons, linear trend tests across ordered groups, and RMST hypothesis tests with pairwise comparisons.

Regression models: Cox proportional hazards with stratification, baseline hazard prediction with confidence intervals, and full diagnostics. Parametric accelerated failure time (AFT) models with Weibull, exponential, log-normal, and log-logistic distributions. Competing risks via Aalen-Johansen and Fine-Gray models. Multi-state transition probabilities.

Visualization: interactive survival curves with confidence bands, censoring marks, and aligned at-risk tables. Forest plots with hazard ratios. Cumulative incidence plots for competing risks. All plots are interactive and publication-ready.

Model evaluation: Concordance index (Harrell’s C-statistic), IPCW Brier scores, integrated Brier scores, and k-fold cross-validation with stratification support.

Built-in data: load bundled datasets (lung, veteran, ovarian, pbc, colon, mgus2) in any supported backend.

Next steps

Key features at a glance

✓ Narwhals-native for dataframe agility ✓ R-validated for trustworthy results
✓ Interactive publication plots ✓ Great Tables integration
✓ Complete toolkit (KM to competing risks) ✓ Broom-compatible tidy outputs
✓ Built-in datasets and R parity tests ✓ Cross-validation with stratification