Survival analysis and time-to-event models
Model when an event happens without pretending that unfinished follow-up means no event.
What you'll learn
- How right-censoring changes the target and why naive labels are biased
- How survival, hazard, and Kaplan-Meier estimates fit together
- How to interpret a Cox proportional-hazards coefficient and test its assumption
- When to choose Cox, survival trees, survival boosting, or a fixed-horizon classifier
- Why the concordance index is useful but insufficient for probability calibration
Before you start
The customer who has not churned yet
It is 4:57 p.m. Your retention model is due before the weekly meeting.
The data contains 10,000 accounts. Nine hundred have canceled. The other 9,100 are marked churn = 0.
But one of those “negatives” signed up two days ago. Another has paid for 18 months. The first customer has only survived two days in your records. They might cancel tomorrow. The second has given you considerably stronger evidence of staying.
A plain classifier sees the same label: zero.
That is the problem survival analysis exists to solve. It models both whether an event happens and when, while keeping track of observations that ended before the event was seen.
The event might be churn, machine failure, loan default, hospital readmission, or conversion. “Survival” is just the traditional name for remaining event-free.
For one subject, write:
Tfor the true time until the event.Cfor the last time you could observe the subject.Y = min(T, C)for the time recorded in your data.event = 1when the event happened before observation ended, otherwiseevent = 0.
When event = 0, you know only that T > Y. The event is right-censored: it lies somewhere to the right of the observed timeline.
Dropping all censored rows is not a safe escape hatch. You preferentially keep people whose event became visible during the study. Labeling censored rows as zero is worse: it turns “not yet” into “never.” Both choices can make the model learn observation length instead of risk.
Two functions, two different questions
The survival function is:
S(t) = P(T > t)
It is the probability that a randomly selected subject remains event-free beyond time t. If S(30) = 0.72, the estimated probability of surviving 30 days is 72 percent. For a single-event churn problem, the probability of churning by day 30 is 1 - S(30).
The hazard function asks a different question. It is the event rate at time t, conditional on having survived until t. For a short interval, the chance of an event is approximately h(t) multiplied by the interval length.
Hazard is not the probability of ever having the event. A hazard of 0.02 per day can describe a roughly constant process whose 30-day survival is exp(-0.02 × 30), or about 0.55. The hazard is a local rate; survival accumulates its effect over time.
The cumulative hazard is the accumulated rate, and the relationship is S(t) = exp(-H(t)). This is why a model can predict a risk score without directly predicting a probability. The score may rank customers correctly while still needing a baseline hazard or calibration step to produce S(30).
Kaplan-Meier, by hand
Kaplan-Meier is the basic non-parametric estimator of a survival curve. It needs no features. It answers: “What fraction appears to remain event-free at each time?”
Suppose seven customers produce these observations:
- Events at days 2, 4, 4, and 6.
- Censoring at days 3, 5, and 8.
At each event time, Kaplan-Meier multiplies the current estimate by the fraction who did not have the event:
(n - d) / n
Here, n is the number at risk immediately before the time and d is the number of events at that time. Censored subjects leave the future risk set, but they do not make the curve drop.
| Time | At risk n | Events d | Censored | Multiplier | Estimated survival |
|---|---|---|---|---|---|
| 2 | 7 | 1 | 0 | 6/7 | 0.857 |
| 3 | 6 | 0 | 1 | 1 | 0.857 |
| 4 | 5 | 2 | 0 | 3/5 | 0.514 |
| 5 | 3 | 0 | 1 | 1 | 0.514 |
| 6 | 2 | 1 | 0 | 1/2 | 0.257 |
| 8 | 1 | 0 | 1 | 1 | 0.257 |
At day 4, the estimate is:
(6/7) × (3/5) = 18/35 = 0.514
The two cancellations at day 4 matter. The customer censored at day 3 does not cause a drop, but removing that customer means only five people are at risk at day 4.
This is a small example, but it contains the core mechanism. Kaplan-Meier uses partial follow-up rather than throwing it away.
The calculation is easy to reproduce with lifelines:
import pandas as pd
from lifelines import KaplanMeierFitter
df = pd.DataFrame(
{
"time": [2, 3, 4, 4, 5, 6, 8],
"event": [1, 0, 1, 1, 0, 1, 0],
}
)
km = KaplanMeierFitter()
km.fit(durations=df["time"], event_observed=df["event"])
print(f"{km.survival_function_at_times(4).iloc[0]:.3f}")
The last line prints 0.514.
Kaplan-Meier is excellent for comparing broad groups, such as free and paid plans. It cannot adjust for five other variables, and it does not give an individual risk prediction unless you assign that person to a group.
Cox proportional hazards
The Cox model adds features while leaving the baseline hazard mostly unspecified:
h(t | x) = h0(t) × exp(beta1 x1 + ... + betap xp)
h0(t) is the baseline hazard. The coefficients describe how features multiply that baseline. This is a semi-parametric model: it estimates covariate effects without requiring a particular shape for the baseline hazard.
Why can Cox avoid specifying h0(t)? At each observed event time, it compares the person who had the event with everyone still at risk at that moment. The baseline hazard is common to that risk set, so it cancels in the relative comparison. The resulting partial likelihood estimates the coefficients from who failed earlier than whom.
A coefficient becomes a hazard ratio after exponentiation. Suppose a fitted model gives support tickets a coefficient of 0.18 per ticket.
- One additional ticket has hazard ratio
exp(0.18) = 1.197, about 20 percent higher instantaneous churn hazard. - The comparison from two tickets to five tickets is
exp(0.18 × 3) = 1.72, about 72 percent higher hazard, holding other features constant.
This is not a 20 percentage-point increase in churn probability. It is not automatically a causal effect either. A frustrated customer may open more tickets because they were already likely to leave.
Cox is a strong first feature-based model when proportional hazards is plausible and interpretability matters. Its risk score is often useful even when absolute survival estimates are not yet calibrated.
When proportional hazards fails
The Cox assumption says that the hazard ratio between two feature values is constant over time. If a feature doubles the hazard, it should do so on day 3 and day 300.
Many products do not behave that way. A discount might trigger a sharp cancellation spike during the first billing cycle, then have almost no effect among customers who stay. A medical treatment might help early and lose its advantage later. The two estimated survival curves may cross.
A practical first symptom is observed group survival curves that cross, or time-specific effect estimates that reverse: one group may look riskier in week one but safer after month three. Scaled Schoenfeld residual plots against time can reveal a trend. A formal test can help, but a plot and domain knowledge are better than worshipping a p-value.
Possible responses:
- Add a feature-by-time interaction when the changing effect is meaningful and known.
- Split time into periods and estimate period-specific effects.
- Stratify on a categorical variable when you need different baseline curves but do not need its coefficient.
- Use an accelerated-failure-time model when time ratios are more natural.
- Use a survival tree or boosting model when nonlinear effects and interactions matter.
Do not quietly report one global hazard ratio after seeing the effect reverse. That number may be a convenient average of two contradictory stories.
Trees and boosting for survival
A regular regression tree trained on observed times treats a censored time as if it were the true event time. A regular classifier has the same problem in a different costume. Use a censoring-aware survival objective.
Survival trees split the data using differences in event timing and survival, often with log-rank-style criteria. Random survival forests average survival curves or cumulative hazards from many trees. Survival gradient boosting can optimize a Cox partial-likelihood objective, an accelerated-failure-time likelihood, or another survival-specific loss.
These models are attractive when a customer with ten tickets behaves very differently from one with one ticket, or when feature interactions matter. Tree/forest models and boosters using AFT or other non-PH losses do not require proportional hazards; a booster using a Cox partial-likelihood loss does.
The price is less transparent interpretation, more tuning, and often weaker extrapolation beyond the observed follow-up. Some implementations produce only a risk score. Others produce a survival curve. Verify which one you have before presenting 1 - S(30) to a product manager; a Cox-style score is not that probability.
The ideas connect naturally to ordinary decision trees and XGBoost, but the loss and handling of censoring are the important differences.
Evaluation: concordance is about ordering
Accuracy asks how many binary labels were correct. Ordinary AUC asks whether positive examples receive higher scores than negative examples. A time-to-event dataset has neither a single final label nor equally complete follow-up.
A customer censored on day 10 might churn on day 11. Calling that customer a negative makes accuracy and AUC measure your censoring process.
The concordance index, or C-index, evaluates ranking while ignoring pairs whose ordering cannot be known. If customer A churns on day 10 while customer B is still observed on day 20, the pair is comparable. A good model gives A the higher risk. If A is censored on day 10 and B churns on day 20, the pair is not safely comparable: A may have churned on day 11.
A C-index of 0.5 is random ordering. A value of 1.0 is perfect ordering among comparable pairs. Ties usually receive half credit. Harrell’s C-index is common, but heavy censoring can bias it; inverse-probability-of-censoring-weighted versions such as Uno’s C can be preferable in that setting.
C-index measures ranking, not calibration or timing. A model can have a C-index of 0.78 and still predict 30-day churn probabilities that are much too high. For a horizon-specific decision, also inspect:
- Censoring-aware calibration of predicted
1 - S(30)using IPCW, pseudo-observations, or an appropriate cumulative-incidence/Kaplan–Meier estimate. - The Brier score or integrated Brier score, usually with censoring weights.
- A censoring-aware definition of time-dependent AUC when ranking at a specified horizon is the decision.
This is the same discipline as picking the right metric: start with the decision, then choose the metric that can actually observe it.
“Churn in the next 30 days”: classifier or survival model?
A fixed-horizon classifier targets:
Y30 = 1 if churn happens by day 30
That target is valid when every evaluated customer is observed through day 30 or churns earlier. Someone active through day 30 is a legitimate negative. Someone who disappears from tracking on day 8 is not.
A survival model uses every observed duration and event flag, then estimates S(30). It naturally handles a customer observed for 8 days and another observed for 90 days, assuming censoring is sufficiently independent of the unobserved event after conditioning on available features.
| Business situation | Good first choice | Why | Main catch |
|---|---|---|---|
| One horizon, complete 30-day follow-up | Classifier | Direct probability and simple operations | Must rebuild labels if the horizon changes |
| Several horizons or uneven follow-up | Cox model | Uses partial follow-up and gives a full time curve | Requires proportional-hazards reasoning |
| Strong nonlinearities and interactions | Survival forest or GBM with an AFT or other non-PH loss | Flexible risk patterns without a proportional-hazards requirement | A GBM using a Cox loss still assumes PH; curves and probabilities need careful calibration |
| Descriptive group comparison, few features | Kaplan-Meier | Transparent estimate of group survival | No individual adjustment |
| Changing effects and a useful time interpretation | AFT or time-varying Cox | Models how features alter event time or effects | More assumptions and more complex reporting |
If the business truly asks only for “will this fully observed account churn by day 30?”, a classifier is often simpler. If accounts arrive continuously and many have not reached day 30, forcing the problem into classification wastes information and invites label bias.
A practical data table usually contains customer_id, an origin timestamp, features available at that origin, time, and event. Split by customer, and often by calendar time as well. A feature such as “support tickets opened during the next 14 days” is future information, not a clever predictor. Keep the timestamp discipline used to avoid data leakage.
Failure modes
| First symptom | Likely cause | Fix |
|---|---|---|
| A Kaplan-Meier curve drops on dates when customers merely vanished | Event coding was reversed | Use event = 1 only for the event; audit a few rows by hand |
| Performance changes dramatically when the study end date moves | Censored rows were labeled negative or discarded | Keep duration and event status; use a survival objective or censoring-weighted horizon method |
| Observed group survival curves cross around day 14 | Proportional hazards is false | Add time effects, stratify, use AFT, or switch to a flexible survival model |
| C-index is strong, but 30-day intervention yield is poor | Ranking was mistaken for calibrated probability | Check horizon calibration and Brier score; recalibrate or use a model that returns probabilities |
| Validation is near-perfect and production collapses | Features were measured after the prediction origin, or users leaked across splits | Freeze feature time and split by entity and deployment time |
The honest limitation
Survival analysis does not reveal events that your data collection never had a chance to see. Most methods need censoring to be independent of the unobserved event, at least after conditioning on recorded covariates. If high-risk customers are more likely to disable tracking, that assumption fails.
Use a censoring model with inverse-probability weighting, run sensitivity analyses, and investigate why follow-up ends. If another event prevents the event of interest, such as death preventing readmission or an upgrade ending churn risk, it is a competing event, not ordinary censoring. Use a competing-risks method when the business question is the real-world probability of that event.
Survival models are also associations, not treatment-effect estimators. For “who should receive this retention offer?”, prediction is only half the job; causal methods are a separate question.
What to remember
- Right-censoring means the event time is known only to be later than the last observation.
- Censored is not negative. Dropping or mislabeling those rows changes the target.
- Survival is the chance of remaining event-free; hazard is the conditional instantaneous event rate.
- Kaplan-Meier handles partial follow-up; Cox adds covariates but assumes proportional hazards.
- C-index evaluates ranking. Horizon calibration tells you whether a predicted 30-day probability deserves trust.
Quick check
Practice this in an interview
All questionsSurvivorship bias occurs when analysis is restricted to the subset of observations that 'survived' some selection process, ignoring the failures that did not. The surviving sample is systematically unrepresentative, inflating estimates of success and hiding the true risk.
Handling outliers starts with understanding whether they are errors, rare genuine observations, or leverage points that reveal real signal. The appropriate response — removal, transformation, robust estimation, or explicit modelling — depends entirely on their cause, not on how extreme they look.
Missing data can be dropped, imputed with a statistic (mean, median, mode), or imputed with a model. The right choice depends on the missing mechanism (MCAR, MAR, MNAR), the fraction of missing data, and the downstream model. Dropping rows is only safe when missingness is rare and random; imputation must always be fit on training data only.
Interviewers ask this to test intellectual honesty, ownership, and how you learn from setbacks — not to embarrass you. The strongest answers name a real failure, explain the root cause clearly, describe what you did to fix or contain the damage, and articulate the lasting lesson you carried forward.