Skip to main content

A high-performance survival analysis library written in Rust with Python bindings

Project description

survival

Crates.io PyPI version License: MIT

A high-performance survival analysis library written in Rust, with a Python API powered by PyO3 and maturin.

Features

  • Core survival analysis routines
  • Cox proportional hazards models with frailty
  • Kaplan-Meier and Aalen-Johansen (multi-state) survival curves
  • Nelson-Aalen estimator
  • Parametric accelerated failure time models
  • Fine-Gray competing risks model
  • Penalized splines (P-splines) for smooth covariate effects
  • Concordance index calculations
  • Person-years calculations
  • Score calculations for survival models
  • Residual analysis (martingale, Schoenfeld, score residuals)
  • Bootstrap confidence intervals
  • Cross-validation for model assessment
  • Statistical tests (log-rank, likelihood ratio, Wald, score, proportional hazards)
  • Sample size and power calculations
  • RMST (Restricted Mean Survival Time) analysis
  • Landmark analysis
  • Calibration and risk stratification
  • Time-dependent AUC
  • Conditional logistic regression
  • Time-splitting utilities

Installation

From PyPI (Recommended)

pip install survival

From Source

Prerequisites

Install maturin:

pip install maturin

Build and Install

Build the Python wheel:

maturin build --release

Install the wheel:

pip install target/wheels/survival-*.whl

For development:

maturin develop --release

Usage

Aalen's Additive Regression Model

from survival import AaregOptions, aareg

data = [
    [1.0, 0.0, 0.5],
    [2.0, 1.0, 1.5],
    [3.0, 0.0, 2.5],
]
variable_names = ["time", "event", "covariate1"]

# Create options with required parameters (formula, data, variable_names)
options = AaregOptions(
    formula="time + event ~ covariate1",
    data=data,
    variable_names=variable_names,
)

# Optional: modify default values via setters
# options.weights = [1.0, 1.0, 1.0]
# options.qrtol = 1e-8
# options.dfbeta = True

result = aareg(options)
print(result)

Penalized Splines (P-splines)

from survival import PSpline

x = [0.1 * i for i in range(100)]
pspline = PSpline(
    x=x,
    df=10,
    theta=1.0,
    eps=1e-6,
    method="GCV",
    boundary_knots=(0.0, 10.0),
    intercept=True,
    penalty=True,
)
pspline.fit()

Concordance Index

from survival import perform_concordance1_calculation

time_data = [1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0]
weights = [1.0, 1.0, 1.0, 1.0, 1.0]
indices = [0, 1, 2, 3, 4]
ntree = 5

result = perform_concordance1_calculation(time_data, weights, indices, ntree)
print(f"Concordance index: {result['concordance_index']}")

Cox Regression with Frailty

from survival import perform_cox_regression_frailty

result = perform_cox_regression_frailty(
    time=[1.0, 2.0, 3.0, 4.0],
    event=[1, 1, 0, 1],
    covariates=[
        [0.2, 1.0],
        [0.1, 0.5],
        [0.4, 1.2],
        [0.3, 0.7],
    ],
    max_iter=20,
    eps=1e-5,
)
print(result["coefficients"])

Person-Years Calculation

from survival import perform_pyears_calculation

# Low-level API: inputs should match ratetable-style dimensions/cuts.
result = perform_pyears_calculation(
    time_data=[1.0, 2.0, 3.0, 1.0, 0.0, 1.0],  # [times..., events...], ny=2
    weights=[1.0, 1.0, 1.0],
    expected_dim=1,
    expected_factors=[0],
    expected_dims=[2],
    expected_cuts=[0.0, 2.0],
    expected_rates=[0.01, 0.02],
    expected_data=[0.5, 1.5, 0.5],
    observed_dim=1,
    observed_factors=[0],
    observed_dims=[2],
    observed_cuts=[0.0, 1.5, 3.0],
    method=0,
    observed_data=[0.5, 1.0, 2.0],
    do_event=1,
    ny=2,
)
print(result.keys())

Kaplan-Meier Survival Curves

from survival import survfitkm, SurvFitKMOutput

# Example survival data
time = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
status = [1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0]  # 1 = event, 0 = censored
weights = [1.0] * len(time)  # Optional: equal weights

result = survfitkm(
    time=time,
    status=status,
    weights=weights,
    entry_times=None,  # Optional: entry times for left-truncation
    position=None,     # Optional: position flags
    reverse=False,     # Optional: reverse time order
    computation_type=0 # Optional: computation type
)

print(f"Time points: {result.time}")
print(f"Survival estimates: {result.estimate}")
print(f"Standard errors: {result.std_err}")
print(f"Number at risk: {result.n_risk}")

Fine-Gray Competing Risks Model

from survival import finegray, FineGrayOutput

# Example competing risks data
tstart = [0.0, 0.0, 0.0, 0.0]
tstop = [1.0, 2.0, 3.0, 4.0]
ctime = [0.5, 1.5, 2.5, 3.5]  # Cut points
cprob = [0.1, 0.2, 0.3, 0.4]  # Cumulative probabilities
extend = [True, True, False, False]  # Whether to extend intervals
keep = [True, True, True, True]      # Which cut points to keep

result = finegray(
    tstart=tstart,
    tstop=tstop,
    ctime=ctime,
    cprob=cprob,
    extend=extend,
    keep=keep
)

print(f"Row indices: {result.row}")
print(f"Start times: {result.start}")
print(f"End times: {result.end}")
print(f"Weights: {result.wt}")

Parametric Survival Regression (Accelerated Failure Time Models)

from survival import survreg, SurvivalFit, DistributionType

# Example survival data
time = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
status = [1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0]  # 1 = event, 0 = censored
covariates = [
    [1.0, 2.0],
    [1.5, 2.5],
    [2.0, 3.0],
    [2.5, 3.5],
    [3.0, 4.0],
    [3.5, 4.5],
    [4.0, 5.0],
    [4.5, 5.5],
]

# Fit parametric survival model
result = survreg(
    time=time,
    status=status,
    covariates=covariates,
    weights=None,          # Optional: observation weights
    offsets=None,          # Optional: offset values
    initial_beta=None,     # Optional: initial coefficient values
    strata=None,           # Optional: stratification variable
    distribution="weibull",  # "extreme_value", "logistic", "gaussian", "weibull", or "lognormal"
    max_iter=20,          # Optional: maximum iterations
    eps=1e-5,             # Optional: convergence tolerance
    tol_chol=1e-9,        # Optional: Cholesky tolerance
)

print(f"Coefficients: {result.coefficients}")
print(f"Log-likelihood: {result.log_likelihood}")
print(f"Iterations: {result.iterations}")
print(f"Variance matrix: {result.variance_matrix}")
print(f"Convergence flag: {result.convergence_flag}")

Cox Proportional Hazards Model

from survival import CoxPHModel, Subject

# Create a Cox PH model
model = CoxPHModel()

# Or create with data
covariates = [[1.0, 2.0], [2.0, 3.0], [1.5, 2.5]]
event_times = [1.0, 2.0, 3.0]
censoring = [1, 1, 0]  # 1 = event, 0 = censored

model = CoxPHModel.new_with_data(covariates, event_times, censoring)

# Fit the model
model.fit(n_iters=10)

# Get results
print(f"Baseline hazard: {model.baseline_hazard}")
print(f"Risk scores: {model.risk_scores}")
print(f"Coefficients: {model.get_coefficients()}")

# Predict on new data
new_covariates = [[1.0, 2.0], [2.0, 3.0]]
predictions = model.predict(new_covariates)
print(f"Predictions: {predictions}")

# Calculate Brier score
brier = model.brier_score()
print(f"Brier score: {brier}")

# Compute survival curves for new covariates
new_covariates = [[1.0, 2.0], [2.0, 3.0]]
time_points = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0]  # Optional: specific time points
times, survival_curves = model.survival_curve(new_covariates, time_points)
print(f"Time points: {times}")
print(f"Survival curves: {survival_curves}")  # One curve per covariate set

# Create and add subjects
subject = Subject(
    id=1,
    covariates=[1.0, 2.0],
    is_case=True,
    is_subcohort=True,
    stratum=0
)
model.add_subject(subject)

Cox Martingale Residuals

from survival import coxmart

# Example survival data
time = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
status = [1, 1, 0, 1, 0, 1, 1, 0]  # 1 = event, 0 = censored
score = [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2]  # Risk scores

# Calculate martingale residuals
residuals = coxmart(
    time=time,
    status=status,
    score=score,
    weights=None,      # Optional: observation weights
    strata=None,       # Optional: stratification variable
    method=0,          # Optional: method (0 = Breslow, 1 = Efron)
)

print(f"Martingale residuals: {residuals}")

Survival Difference Tests (Log-Rank Test)

from survival import survdiff2, SurvDiffResult

# Example: Compare survival between two groups
time = [1.0, 2.0, 3.0, 4.0, 5.0, 1.5, 2.5, 3.5, 4.5, 5.5]
status = [1, 1, 0, 1, 0, 1, 1, 1, 0, 1]
group = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2]  # Group 1 and Group 2

# Perform log-rank test (rho=0 for standard log-rank)
result = survdiff2(
    time=time,
    status=status,
    group=group,
    strata=None,  # Optional: stratification variable
    rho=0.0,      # 0.0 = log-rank, 1.0 = Wilcoxon, other = generalized
)

print(f"Observed events: {result.observed}")
print(f"Expected events: {result.expected}")
print(f"Chi-squared statistic: {result.chi_squared}")
print(f"Degrees of freedom: {result.degrees_of_freedom}")
print(f"Variance matrix: {result.variance}")

Built-in Datasets

The library includes 33 classic survival analysis datasets:

from survival import load_lung, load_aml, load_veteran

# Load the lung cancer dataset
lung = load_lung()
print(f"Columns: {lung['columns']}")
print(f"Number of rows: {len(lung['data'])}")

# Load the acute myelogenous leukemia dataset
aml = load_aml()

# Load the veteran's lung cancer dataset
veteran = load_veteran()

Available datasets:

  • load_lung() - NCCTG Lung Cancer Data
  • load_aml() - Acute Myelogenous Leukemia Survival Data
  • load_veteran() - Veterans' Administration Lung Cancer Study
  • load_ovarian() - Ovarian Cancer Survival Data
  • load_colon() - Colon Cancer Data
  • load_pbc() - Primary Biliary Cholangitis Data
  • load_cgd() - Chronic Granulomatous Disease Data
  • load_bladder() - Bladder Cancer Recurrences
  • load_heart() - Stanford Heart Transplant Data
  • load_kidney() - Kidney Catheter Data
  • load_rats() - Rat Treatment Data
  • load_stanford2() - Stanford Heart Transplant Data (Extended)
  • load_udca() - UDCA Clinical Trial Data
  • load_myeloid() - Acute Myeloid Leukemia Clinical Trial
  • load_flchain() - Free Light Chain Data
  • load_transplant() - Liver Transplant Data
  • load_mgus() - Monoclonal Gammopathy Data
  • load_mgus2() - Monoclonal Gammopathy Data (Updated)
  • load_diabetic() - Diabetic Retinopathy Data
  • load_retinopathy() - Retinopathy Data
  • load_gbsg() - German Breast Cancer Study Group Data
  • load_rotterdam() - Rotterdam Tumor Bank Data
  • load_logan() - Logan Unemployment Data
  • load_nwtco() - National Wilms Tumor Study Data
  • load_solder() - Solder Joint Data
  • load_tobin() - Tobin's Tobit Data
  • load_rats2() - Rat Tumorigenesis Data
  • load_nafld() - Non-Alcoholic Fatty Liver Disease Data
  • load_cgd0() - CGD Baseline Data
  • load_pbcseq() - PBC Sequential Data
  • load_hoel() - Hoel's Cancer Survival Data
  • load_myeloma() - Myeloma Survival Data
  • load_rhdnase() - rhDNase Clinical Trial Data

API Reference

The public Python surface is broad and evolves quickly. For the most accurate, version-matched signatures, use the checked-in type stubs:

To inspect available symbols at runtime:

import survival

public_names = [name for name in dir(survival) if not name.startswith("_")]
print(public_names)

PSpline Options

The PSpline class provides penalized spline smoothing:

Constructor Parameters:

  • x: Covariate vector (list of floats)
  • df: Degrees of freedom (integer)
  • theta: Roughness penalty (float)
  • eps: Accuracy for degrees of freedom (float)
  • method: Penalty method for tuning parameter selection. Supported methods:
    • "GCV" - Generalized Cross-Validation
    • "UBRE" - Unbiased Risk Estimator
    • "REML" - Restricted Maximum Likelihood
    • "AIC" - Akaike Information Criterion
    • "BIC" - Bayesian Information Criterion
  • boundary_knots: Tuple of (min, max) for the spline basis
  • intercept: Whether to include an intercept in the basis
  • penalty: Whether or not to apply the penalty

Methods:

  • fit(): Fit the spline model, returns coefficients
  • predict(new_x): Predict values at new x points

Properties:

  • coefficients: Fitted coefficients (None if not fitted)
  • fitted: Whether the model has been fitted
  • df: Degrees of freedom
  • eps: Convergence tolerance

Development

Install development dependencies:

pip install -e ".[dev,test,sklearn]"

Build the extension in your current environment:

maturin develop --release

Build the Rust library:

cargo build

Run Rust tests:

cargo test

Run Python tests:

pytest python/tests -v

Format and lint:

cargo fmt
ruff check .

The codebase is organized with:

  • Core routines in src/
  • Rust unit/integration tests in src/tests/
  • Python binding tests in python/tests/
  • R validation fixtures and archived reference cases in test/
  • Python bindings using PyO3

Dependencies

Primary dependencies are defined in Cargo.toml and pyproject.toml, including:

Compatibility

  • This build is for Python only. R/extendr bindings are currently disabled.
  • Python 3.11+ and Rust 1.93+ are required.
  • macOS users: Ensure you are using the correct Python version and have Homebrew-installed Python if using Apple Silicon.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

survival-1.2.15.tar.gz (1.5 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

survival-1.2.15-cp314-cp314-win_amd64.whl (5.4 MB view details)

Uploaded CPython 3.14Windows x86-64

survival-1.2.15-cp314-cp314-manylinux_2_39_x86_64.whl (5.7 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.39+ x86-64

survival-1.2.15-cp314-cp314-manylinux_2_39_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.39+ ARM64

survival-1.2.15-cp314-cp314-macosx_11_0_arm64.whl (4.6 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

survival-1.2.15-cp314-cp314-macosx_10_12_x86_64.whl (5.2 MB view details)

Uploaded CPython 3.14macOS 10.12+ x86-64

File details

Details for the file survival-1.2.15.tar.gz.

File metadata

  • Download URL: survival-1.2.15.tar.gz
  • Upload date:
  • Size: 1.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for survival-1.2.15.tar.gz
Algorithm Hash digest
SHA256 240fed84e746aa688cdbb2c5001b60565f6f0d56fd2e8535e32ea7bf4c6709c5
MD5 0531724c3216c38efd4950aa695b924c
BLAKE2b-256 6c6b401b1f2a46c35456e3836b64632e049f30c20140fae9de8749d645a83ba9

See more details on using hashes here.

File details

Details for the file survival-1.2.15-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: survival-1.2.15-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 5.4 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for survival-1.2.15-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 af85e21b0a6ea59ca9db4d83b445e69f8c01a4d8d30878156401cf9680870e67
MD5 a878e87eae8d037103481c101ce6ac9c
BLAKE2b-256 657f93247fc12b8667d4cdc7a582799f48e2ed4de8a71bd2b723381debc2d7bc

See more details on using hashes here.

File details

Details for the file survival-1.2.15-cp314-cp314-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for survival-1.2.15-cp314-cp314-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 0c6a17bc4434024b37e38fd0241db6e9fe9920c57c11b6dc7e7da28b05958108
MD5 1056a61c63bd0302828bd06c7d8cf1ad
BLAKE2b-256 c19481305d6d1d70a0c28bdedcd05eae38c6b69ed593d0e4f67cf128ae5a1eac

See more details on using hashes here.

File details

Details for the file survival-1.2.15-cp314-cp314-manylinux_2_39_aarch64.whl.

File metadata

File hashes

Hashes for survival-1.2.15-cp314-cp314-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 d0aeb90a1115ef6662c3c4fb289734d48e35be4037a74d097736daa8aaf63fcf
MD5 9176497e7732ba03e517d1c8961848e1
BLAKE2b-256 377169c041d7907ee96991530c04034ec637b15a45a7ab58c4a568e158ffcaca

See more details on using hashes here.

File details

Details for the file survival-1.2.15-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for survival-1.2.15-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 09a8d75de1bcb6b8667e5a30ba5b0b28d1e2d1abaceccc1ad7263f84d6bc966b
MD5 f7b323ba302fa385ef6025ed7b83331d
BLAKE2b-256 5bacb1abbf70e222544a8ed08630d941496a88e7adbbae07d6794f3fcc8573d3

See more details on using hashes here.

File details

Details for the file survival-1.2.15-cp314-cp314-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for survival-1.2.15-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8659e37e1bfc816e713ae58f2195b6e26c569cde9c7af5c0a35d3daf9f82c5de
MD5 2bc6925017434833e4c1be4802437b1c
BLAKE2b-256 574ad3d86e6e9d88f1eae450fe719472dbcb08810f10523e11c0296e2643224e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page