The Kaplan–Meier estimator plots the probability that loans remain current over time. Each loan contributes its own timeline, so the curve can account for incomplete observations, such as loans still active when the observation window ends. section 4.2.2
Read the curve as follows:
- It starts at 1.0; each downward step marks a default. section 4.2.2
- A value near 0.90 at month 12 indicates about 10% of accounts have defaulted. section 4.2.2
- Unlike vintage analysis, it follows accounts individually rather than aggregating outcomes by cohort. section 4.2.2
Listing 4.2 Survival analysis example [4]
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from lifelines import KaplanMeierFitter
np.random.seed(42)
# Generate 50 synthetic loans with ~10% default by 12 months
N = 50
time_to_default = []
event_observed = []
for _ in range(N):
r = np.random.rand() #1
if r < 0.1: #2
possible_months = [3,4,5,6,7,8,9,10]
d_month = np.random.choice(possible_months)
time_to_default.append(d_month)
event_observed.append(1) #3
else:
time_to_default.append(12)
event_observed.append(0) #4
df_surv = pd.DataFrame({
"loan_id": range(1, N+1),
"time_to_default": time_to_default,
"event_observed": event_observed
})
# Fit the Kaplan–Meier model
kmf = KaplanMeierFitter() #5
kmf.fit(
durations=df_surv["time_to_default"],
event_observed=df_surv["event_observed"],
label="Loan Survival"
)
# Plot the KM survival function
kmf.plot_survival_function() #6
plt.title("Kaplan–Meier Survival Curve (~10% Default)")
plt.xlabel("Months on Book")
plt.ylabel("Survival Probability")
plt.grid(True)
plt.show()
Inspect the Python example fitting a Kaplan–Meier curve to 50 synthetic loans with observed-default indicators. section 4.2.2
