A/B tests · AdvancedTime to event: Kaplan–Meier

An online Kaplan–Meier curve and survival analysis: retention, time to purchase and subscription length, counting people who have not had the event yet. The log-rank test, medians, RMST and a step-by-step solution.

Your numbers stay in the browser and are never sent anywhere

01Calculator02About03Check in Python / R04Guides05Questions06Related
01

Calculator

Try
The event is a user leaving; time is days since sign-up. Times separated by commas; 12+ means the event has not happened yet. Or two columns from Excel: time and 1/0.
8 observations · events 5 · censored 3
8 observations · events 7 · censored 1
Test
The difference is borderline.
Median time to leaving: “New onboarding” 7 days, “Old onboarding” 15 days; log-rank p = 0.055.
What to do next: Collect more observations, or wait for the censored ones to reach the event.
Share without the event · S(t)
0%25%50%75%100%051015202530
Old onboardingNew onboardingcensoreddashed 50% line: median
Median · Old onboarding
15 days
CI 5…∞
Median · New onboarding
7 days
CI 3…18
No event by 10 days
75% · 33%
Old onboarding · New onboarding
Mean up to τ = 30 (RMST)
17.7 · 9.5
difference −8.2 days
Log-rank
χ² = 3.670
p = 0.055 · df 1
Observations · events
8/5 · 8/7
censored: 3 · 1
Life table
TimeAt riskEventsS(t)95% CI
5810.8750.387…0.981
8710.7500.315…0.931
12610.6250.229…0.861
15410.4690.120…0.763
22210.2340.013…0.616
02

About

Censoring is not missing data

A user who has not left yet is still data: they lasted at least that many days.

The median instead of the mean

The mean time cannot be calculated while some people have not had the event. The median and S(t) can.

Log-rank compares whole curves

It looks at every event time, not at a single point.

03

Check in Python / R

Check in Python / R
from lifelines.statistics import multivariate_logrank_test

time = [5, 8, 12, 12, 15, 20, 22, 30, 3, 4, 6, 7, 9, 10, 14, 18]
event = [1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1]
group = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]

r = multivariate_logrank_test(time, group, event)
r.test_statistic, r.p_value
# 3.67, 0.0554
# When S is exactly 0.5: R takes the midpoint to the next event (8.5), lifelines the next time (10), this page 7

The median here is the first time where S(t) ≤ 0.5. When S is exactly 0.5, other software differs: R takes the midpoint to the next event (8.5), lifelines takes the next time (10), and this page shows 7.

04

Related guides

All guides
A/B testing: how to run a testSeven steps from hypothesis to conclusion, a hypothesis template, 12 common mistakes and a glossary8 minHow many of your A/B test wins are falseWhy every third win is false at α = 5%: a grid of 100 tests, a table and a simulation8 minHow not to run an A/B testEight mistakes with live demonstrations and a printable checklist12 min
05

Frequently asked questions

It is a step chart of the share of people who have not had the event yet. Each step is an event time: the share falls by the fraction of people still at risk who reached the event. Censored people create no step but reduce the number at risk, so the curve neither inflates nor understates retention.

Updated