AI Hints
Home›Data Science Tutorial›Randomness in Business
Data Science · Lesson 50 of 101

How Long Do Customers Stay?

Survival analysis.

⏱ 2 min read▶ Video at 1:25:31🎓 Free
Watch this lesson in the Data Science courseWatch on YouTube ↗Full Data Science course

You want to know how long customers stay. Simple, surely? Just average their lifetimes. But there's a trap. Many customers haven't left yet. You don't know when they'll leave. If you ignore that, then your answer will be badly wrong. Doctors faced the same problem in the nineteen fifties, with patients still alive at the end of a study. They solved it, and we can borrow their method.

How Long Do Customers Stay?
From the video: How Long Do Customers Stay?
  • How long do customers stay?
  • Many haven't left yet
  • Doctors solved this in the 1950s

The Kaplan-Meier curve

We simulate customers with a true average life of twelve months without a card, and twenty six with one. But we only watch them for between three and twenty four months. For each month, Kaplan Meier asks, of the people who were still being observed, what share left? Then it multiplies those together. Customers who are still active count for as long as we saw them, and then they quietly drop out of the calculation. Run it. At twelve months, thirty seven percent of non members remain, and sixty one percent of members. Now look at the last line. A naive average says seven and a half months. The truth is twelve. Ignoring people who haven't left yet gets it very wrong.

survival.pypython
import numpy as np
import pandas as pd

rng = np.random.default_rng(0)
n = 3000
loyal = rng.integers(0, 2, n)
life = rng.exponential(np.where(loyal == 1, 26, 12))
seen = rng.uniform(3, 24, n)
df = pd.DataFrame({"t": np.minimum(life, seen).round(), "left": life <= seen, "loyal": loyal})

def survival(d):
    s, curve = 1.0, {}
    for month in sorted(d["t"].unique()):
        at_risk = (d["t"] >= month).sum()
        left = ((d["t"] == month) & d["left"]).sum()
        s *= 1 - left / at_risk
        curve[month] = s
    return pd.Series(curve)

naive = df[df.loyal == 0]["t"].mean()
for name, group in [("No card", df[df.loyal == 0]), ("Card", df[df.loyal == 1])]:
    print(f"{name:<8} still here at 12 months: {survival(group).loc[:12].iloc[-1]:.0%}")
print(f"Naive average life, no card: {naive:.1f} months (true 12)")
Output
No card  still here at 12 months: 37%
Card     still here at 12 months: 61%
Naive average life, no card: 7.5 months (true 12)

Where survival analysis helps

This has lots of business uses. How long until a customer leaves? How long until a machine fails? How long until a trial user pays? How long until an employee quits? Any time that you're measuring time until something happens, and it hasn't yet happened for everyone, this is the right tool. The lifelines library in Python handles this, and more, in one line.

Customer churntime to leaving
Machinestime to failure
Trialstime to paying
lifelinesthe Python library

Summary

Count people who haven't left yet, properly. Next, how to make a decision when you don't know the numbers.

Key takeaways
  • Unfinished lifetimes matter
  • Kaplan-Meier handles them
  • Naive averages are too low
Next up: Monte Carlo Simulation — making decisions with uncertain numbers