A high-performance survival analysis library written in Rust with Python bindings
This project has been archived.
The maintainers of this project have marked this project as archived. No new releases are expected.
Project description
survival-rs
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
- Kaplan-Meier and Aalen-Johansen (multi-state) survival curves
- Parametric accelerated failure time models
- Penalized splines (P-splines) for smooth covariate effects
- Concordance index calculations
- Person-years calculations
- Score calculations for survival models
- Residual analysis
Installation
From PyPI (Recommended)
pip install survival-rs
From Source
Prerequisites
- Python 3.12 or 3.13 (recommended: 3.12)
- Rust toolchain (see rustup.rs)
- maturin
- BLAS libraries (required at runtime):
- Arch Linux:
sudo pacman -S openblas - Ubuntu/Debian:
sudo apt-get install libopenblas-dev - Fedora:
sudo dnf install openblas-devel - macOS:
brew install openblas
- Arch Linux:
Install maturin:
pip install maturin
Build and Install
Build the Python wheel:
maturin build --release
Install the wheel:
pip install target/wheels/survival_rs-0.1.0-*.whl
For development:
maturin develop
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"]
options = AaregOptions(
formula="time + event ~ covariate1",
data=data,
variable_names=variable_names,
weights=None,
subset=None,
na_action=None,
qrtol=1e-8,
nmin=None,
dfbeta=False,
taper=0.0,
test=[],
cluster=None,
model=False,
x=False,
y=False,
)
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_data=[...],
status_data=[...],
covariates=[...],
# ... other parameters
)
Person-Years Calculation
from survival import perform_pyears_calculation
result = perform_pyears_calculation(
time_data=[...],
weights=[...],
# ... other parameters
)
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}")
API Reference
Classes
AaregOptions: Configuration options for Aalen's additive regression modelPSpline: Penalized spline class for smooth covariate effectsCoxPHModel: Cox proportional hazards model classSubject: Subject data structure for Cox PH modelsSurvFitKMOutput: Output from Kaplan-Meier survival curve fittingFineGrayOutput: Output from Fine-Gray competing risks modelSurvivalFit: Output from parametric survival regressionDistributionType: Distribution types for parametric models (extreme_value, logistic, gaussian, weibull, lognormal)SurvDiffResult: Output from survival difference tests (log-rank test)
Functions
aareg(options): Fit Aalen's additive regression modelsurvfitkm(...): Fit Kaplan-Meier survival curvessurvreg(...): Fit parametric accelerated failure time modelssurvdiff2(...): Perform survival difference tests (log-rank, Wilcoxon, etc.)coxmart(...): Calculate Cox martingale residualsfinegray(...): Fine-Gray competing risks model data preparationperform_concordance1_calculation(...): Calculate concordance index (version 1)perform_concordance3_calculation(...): Calculate concordance index (version 3)perform_concordance_calculation(...): Calculate concordance index (version 5)perform_cox_regression_frailty(...): Fit Cox proportional hazards model with frailtyperform_pyears_calculation(...): Calculate person-years of observationperform_pystep_calculation(...): Perform step calculationsperform_pystep_simple_calculation(...): Perform simple step calculationsperform_score_calculation(...): Calculate score statisticsperform_agscore3_calculation(...): Calculate score statistics (version 3)
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 basisintercept: Whether to include an intercept in the basispenalty: Whether to apply the penalty
Methods:
fit(): Fit the spline model, returns coefficientspredict(new_x): Predict values at new x points
Properties:
coefficients: Fitted coefficients (None if not fitted)fitted: Whether the model has been fitteddf: Degrees of freedomeps: Convergence tolerance
Development
Build the Rust library:
cargo build
Run tests:
cargo test
Format code:
cargo fmt
The codebase is organized with:
- Core routines in
src/ - Tests and examples in
test/ - Python bindings using PyO3
Dependencies
- PyO3 - Python bindings
- ndarray - N-dimensional arrays
- numpy - NumPy integration
- ndarray-linalg - Linear algebra
- itertools - Iterator utilities
- ndarray-stats - Statistical functions
- statrs - Statistical distributions
- thiserror - Error handling
Compatibility
- This build is for Python only. R/extendr bindings are currently disabled.
- macOS users: Ensure you are using the correct Python version and have Homebrew-installed Python if using Apple Silicon.
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file survival_rs-0.1.0.tar.gz.
File metadata
- Download URL: survival_rs-0.1.0.tar.gz
- Upload date:
- Size: 172.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a7678d5d3b954fdfca2e1328ab9dc15a47fff3358cdf7c4e22cb7e517bf4700
|
|
| MD5 |
a670df286d2d597aa6f91b8179e2741c
|
|
| BLAKE2b-256 |
7aa9443756a99bd0834d216fb5b92bda6a0e96426e20240b148e388ecd48e890
|
File details
Details for the file survival_rs-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: survival_rs-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 682.5 kB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc68647defc0869b848ce486f271c2b8a1c6cc043c7ff02e33ba32ed5f08587d
|
|
| MD5 |
cabef5c87bd1da311c766d23ff0aa434
|
|
| BLAKE2b-256 |
c0e2d7cd70eb8cfe7c7b65f8445933b1919568817d55e5f32bdd3f189e515f90
|
File details
Details for the file survival_rs-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl.
File metadata
- Download URL: survival_rs-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl
- Upload date:
- Size: 741.4 kB
- Tags: CPython 3.12, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4764976168846a1573e8038416d0b46c7e53078f3b84c800837c348b982e5676
|
|
| MD5 |
7e00378984c807fc376cd891a0fc8eab
|
|
| BLAKE2b-256 |
e1b063c8e83eb0c4aa322d93c59ab9b54d05e26e5a6bae9661d2189a0cbcf9ce
|
File details
Details for the file survival_rs-0.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: survival_rs-0.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 11.2 MB
- Tags: CPython 3.8, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01441be09f10873135303fcd565faae820e53789c482272d45188f1f1bb1932f
|
|
| MD5 |
52beb9daf75f30b76e7b8052ef894d06
|
|
| BLAKE2b-256 |
2b53a34e4d7e44da1875e5b1c6944ba410274189af627dc2e5f9917a39de9998
|