A lender needs to know when loans default, not only how many eventually default. Survival analysis, also called time-to-event analysis, tracks each loan from observation to an event such as default. It can retain loans that have not defaulted or reached maturity as partial observations rather than treating their unknown future outcomes as defaults. section 4.2.2
Vintage analysis plots cumulative defaults for monthly loan cohorts. It can flag a newer cohort defaulting faster, but a cohort-level curve does not identify which individual loans contribute to that pattern. Survival analysis works at the loan level and can incorporate borrower characteristics such as credit score, income, and usage patterns for more precise risk predictions. section 4.2.2
A basic Kaplan–Meier workflow is:
- Record an observation duration for each loan and an event indicator distinguishing observed defaults from loans still without an observed default. section 4.2.2
- Fit a Kaplan–Meier estimator to obtain a stepwise survival curve: the estimated probability that a loan remains current at each point in time. section 4.2.2
- Inspect when the curve falls. Each downward step represents a default; use the timing alongside cohort trends when investigating underwriting or economic changes. section 4.2.2
Twelve-month loan portfolio
A synthetic portfolio contains 50 loans, with roughly 10% set to default within 12 months. Defaulted loans receive a default month and an observed-event indicator; the others are recorded at month 12 without an observed event. The resulting Kaplan–Meier curve stays flat between defaults and drops when defaults occur. Production analysis would replace these simulated fields with portfolio observations. 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()
Python example generating loan durations and event indicators and fitting a Kaplan–Meier model with lifelines. section 4.2.2
Default timing helps credit teams refine acceptance criteria, investigate risk signals, and monitor portfolio performance. In a credit system, time-aware modeling sits alongside data governance, decision strategy, and the application layer; an illustrative survival curve alone is not a complete lending decision process. section 4.2.2 section 4.6

