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.14.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.14-cp314-cp314-win_amd64.whl (5.4 MB view details)

Uploaded CPython 3.14Windows x86-64

survival-1.2.14-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.14-cp314-cp314-manylinux_2_39_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.39+ ARM64

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

Uploaded CPython 3.14macOS 11.0+ ARM64

survival-1.2.14-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.14.tar.gz.

File metadata

  • Download URL: survival-1.2.14.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.14.tar.gz
Algorithm Hash digest
SHA256 993893b9d6c18cfb3d69407a2731c410f2e921f73f59082a9aed2c20dc5eefbb
MD5 c5860bb259909d84debceab1ae80eaeb
BLAKE2b-256 3352f39a086dc78a56bccab42cc3503ce72fa2566c1b593116cede107c92dd71

See more details on using hashes here.

File details

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

File metadata

  • Download URL: survival-1.2.14-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.14-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 2001da5d5690c15c2381887ff8677feec262e5fad04f5a5908e30130aec3dec8
MD5 8d9ab6ee47f9d5c6451fa7df198ea325
BLAKE2b-256 1c0e7e14c12daedc0a0c77bc39687003fae82f5aa8f4a37aaeb60f33544634c1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for survival-1.2.14-cp314-cp314-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 767022b27dba11e06c952db550910effca3a708fadaf524ea1188d63e6b29a87
MD5 0a7ae7f8a029e28e96a3a742cde032fd
BLAKE2b-256 b2e28bb6c0f1aea985839b8d0d4f86035dc6086a04e5ff058eb1a4c5516085a9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for survival-1.2.14-cp314-cp314-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 e393ea748e986493c47a873eef3bd0c90f96ac43ae2b07691b1f0d3faf480cd7
MD5 8bb0817d9b743e6cb392314766d2ec99
BLAKE2b-256 3e6594ba667de8fe91807dde8247bd3b3381f142308033d477d73b5d7e7b5197

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for survival-1.2.14-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ee645a36004a294f67a2a12759abd94635ed9b11cd32a3e715864944cda46ec9
MD5 c17bcd2ad3fbf7a0e0f2652d171a69e8
BLAKE2b-256 a16bb1d20e1b2b71f910e342a2af506db76e16054856c033ae9ea01825a04021

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for survival-1.2.14-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3ed668cbe9404bf92244e9bac009a08623a540d616d6e9e1fc191e0219ac31dd
MD5 07fcedb2af620aeb9dd02b0eb75052c4
BLAKE2b-256 779ce79c608c9dc8adadf62f6374f3c6d9244aff5fa9e812740532f754d4ee31

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