Open-source project
sebp/scikit-survival avatar
sebp/scikit-survival

scikit-survival: Time-to-Event Models That Behave Like scikit-learn Estimators

Survival analysis built on top of scikit-learn

1,321 stars230 forksPythonGPL-3.0

At a glance

What is it?
scikit-survival wraps censored-data survival models in the scikit-learn estimator API, so the same pipelines, cross-validation and preprocessing code you already use can fit Cox models and random survival forests. The catch is a GPL-3.0 licence and a dependency set that moves fast.
Who is it for?
Adopt scikit-survival if your team already writes scikit-learn pipelines and your data has right-censored event times, and if GPL-3.0 is acceptable for how you ship. Do not adopt it if you need a permissive licence, if your data is uncensored and a plain regressor would do, or if you need a model family the user guide does not list.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The censoring problem scikit-learn does not solve

Standard supervised learning assumes every label is observed. Survival data breaks that assumption. The README describes a clinical study where patients are monitored for a fixed period: if a patient has an event, the exact time is recorded, but if the patient remains event-free when the study ends, the record is right censored and it is unknown whether an event happened afterwards. Dropping those rows biases the result toward short times. Treating the censoring time as the event time biases it the other way. scikit-survival exists to give you models that consume the censored label directly instead of forcing you to throw information away. The audience is therefore narrow and specific: statisticians and ML engineers working with clinical trial data, churn with observation windows, equipment failure logs, or any dataset where the outcome is a duration plus a flag. If your labels are complete, this library is solving a problem you do not have.

What the estimator API actually buys you

The design decision that defines the project is stated plainly in the README: it is built on top of scikit-learn and lets you do survival analysis while using scikit-learn for preprocessing and cross-validation. In practice that means the models are exposed as estimators with fit and predict methods that plug into Pipeline, GridSearchCV and the rest of the ecosystem, rather than as a separate modelling dialect with its own data structures and its own splitting logic. The README points to a user guide that covers the key concepts, an overview of available survival models, and hands-on Jupyter notebook examples. That is the honest boundary of what can be verified from the repository material alone: the estimator surface is the selling point, and the specific model families are enumerated in the user guide rather than in the README. The censored label itself is not a plain array, so the integration is not free. You still have to construct the structured outcome the library expects, and any custom transformer you write has to pass that structure through untouched. The benefit is that everything downstream of the label, scaling, encoding, imputation, resampling, hyperparameter search, is code you have already written for other projects.

Installation and the dependency surface

The README gives the conda-forge route as the easiest option:

conda install -c conda-forge scikit-survival

It also states that you can install from PyPI or from source, with the details in the online installation page rather than in the README. The requirements list is where the real cost sits. Python 3.11 or later. numpy 2.0.0 or later, pandas 2.2.0 or later, scikit-learn 1.9, scipy, narwhals 2.0.1 or later, joblib, numexpr, and three solver packages: clarabel, ecos and osqp. A C/C++ compiler is required, which suggests compiled extensions are built during installation. The pinned minimums are aggressive. numpy 2.0.0 and pandas 2.2.0 are not old releases, and scikit-learn 1.9 is named as a single version rather than a range. If you are pinned to an older scientific Python stack for other reasons, expect a resolution conflict. The three solvers are also worth noting: they are convex optimisation backends, and having all three as hard requirements means the install pulls in numerical code you may never call. Conda-forge is the path of least resistance here because it resolves compiled dependencies as binaries rather than building them.

Where the abstraction leaks

Building on scikit-learn's API is a genuine convenience and also a constraint. scikit-learn's conventions assume a two-dimensional feature matrix and a target array. Survival targets carry a time and an event indicator together, so the target is structured, and every tool in the chain that assumes a flat y needs an adapter or does not apply. The README does not enumerate which scikit-learn utilities work unmodified and which do not, and that is the first thing a prospective user should establish by reading the user guide rather than assuming. There is a second, quieter issue. Survival metrics are not scikit-learn metrics. Concordance, integrated Brier score and time-dependent AUC are not part of the scikit-learn API, so model selection cannot lean entirely on the ecosystem you adopted the library for. You get the preprocessing and the search machinery, not the evaluation machinery. Anyone expecting a drop-in replacement for accuracy_score will be disappointed, and the README does not promise otherwise. It is worth saying directly: the marketing phrase is 'built on top of scikit-learn', but the seam between the two is exactly where the work remains.

The licence is the adoption decision

scikit-survival is GPL-3.0, and the repository carries the badge and a COPYING file to that effect. This is not a footnote. Many Python data libraries are BSD or MIT precisely so they can be embedded in closed products without a second thought. GPL-3.0 is a copyleft licence, and its obligations attach to distribution of derivative works in ways that permissive licences do not. If you are building an internal analysis tool that never leaves your organisation, the practical difference is usually small. If you are shipping a product that links this library, the analysis changes and belongs with your legal team, not with a blog post. I am not giving legal advice and cannot: the boundary between linking, importing and mere aggregation is a question for a lawyer who knows your distribution model. What I can say is that the licence is the single fact most likely to rule this project out for a commercial team, and it deserves to be checked before any technical evaluation, not after.

The alternative: lifelines and the all-in-one approach

The obvious comparison is lifelines, a survival analysis library that does not attempt scikit-learn compatibility. The difference in approach is architectural. lifelines supplies its own model classes, its own plotting helpers and its own statistical summaries, and it is designed for analysts who want a self-contained survival toolkit. scikit-survival supplies estimators that conform to someone else's interface, and it is designed for people who already live inside scikit-learn pipelines and want survival models to be ordinary components in them. Neither approach is strictly better. If your workflow is notebooks and statistical reporting, lifelines' integrated surface is less friction. If your workflow is a Pipeline object with a ColumnTransformer and a GridSearchCV, scikit-survival is the one that fits without a rewrite, because the search and preprocessing code is unchanged. The trade-off is that scikit-survival inherits scikit-learn's version churn and its abstraction boundaries, while a self-contained library controls its own surface. Pick based on where your existing code lives, not on a feature checklist. The README itself does not name any alternative, so this comparison rests on the architectural difference visible in the two projects' stated designs, not on any benchmark.

Maintenance cadence and upgrade cost

The release history in the repository shows v0.26.0 in December 2025, v0.27.0 in February 2026, and v0.28.0 in July 2026, with the last push to main in September 2026. That is a steady cadence of roughly one minor release every few months, and the project is not archived. For a library that tracks scikit-learn and numpy, that cadence is a maintenance requirement you inherit, not just a sign of activity. The requirement list names scikit-learn 1.9 and numpy 2.0.0 or later as minimums, which means the library moves with its upstreams rather than pinning to old ones. If your environment is frozen for regulatory or reproducibility reasons, you will either be upgrading your whole scientific stack to match or staying on an older scikit-survival release. The README points to release notes for notable changes, and those are the right thing to read before bumping a minor version, because a change in a solver dependency or a scikit-learn API shift can surface as a behaviour change in your model rather than as an import error. The project also asks that you cite the Pölsterl 2020 JMLR paper, which is a low-cost obligation and a reasonable one.

Editorial conclusion

Adopt scikit-survival if your team already writes scikit-learn pipelines and your data has right-censored event times, and if GPL-3.0 is acceptable for how you ship. Do not adopt it if you need a permissive licence, if your data is uncensored and a plain regressor would do, or if you need a model family the user guide does not list. Before committing, install it from conda-forge, fit one model on your own data, and check whether the estimator you need exists and whether its dependency pins (numpy 2.0.0 or later, scikit-learn 1.9, pandas 2.2.0 or later) resolve inside your existing environment.

Official sources

  1. Issues
  2. License: GPL-3.0
  3. README
  4. Releases
  5. sebp/scikit-survival on GitHub
Community notes

Community notes