Python 생존분석 완벽 가이드: lifelines로 고객 이탈 예측하기 (Kaplan-Meier, Cox 회귀 실습)

Updated Feb 6, 2026

생존분석이란?

생존분석(Survival Analysis)은 특정 이벤트가 발생하기까지의 시간을 분석하는 통계 기법입니다. 원래 의학 분야에서 환자의 생존 기간을 연구하기 위해 개발되었지만, 현재는 다양한 분야에서 활용됩니다.

분야 이벤트 예시
의료 환자 사망, 질병 재발
비즈니스 고객 이탈, 구독 해지
기계 부품 고장, 시스템 장애
마케팅 재구매, 캠페인 반응

생존분석의 핵심은 검열(Censoring) 데이터를 다룰 수 있다는 점입니다. 관찰 기간 동안 이벤트가 발생하지 않은 경우(우측 검열)도 분석에 활용할 수 있습니다.

lifelines 라이브러리 소개

lifelines는 Python에서 생존분석을 수행하는 가장 인기 있는 라이브러리입니다. Kaplan-Meier 추정, Cox 비례위험모형, 다양한 회귀 모델을 지원합니다.

# 설치
pip install lifelines

# 기본 import
from lifelines import KaplanMeierFitter, CoxPHFitter
from lifelines.datasets import load_waltons
import pandas as pd
import matplotlib.pyplot as plt

Kaplan-Meier 추정: 생존 곡선 그리기

Kaplan-Meier 추정은 시간에 따른 생존 확률을 계산하는 비모수적 방법입니다. 검열 데이터를 고려하여 각 시점의 생존율을 추정합니다.

실습: 고객 이탈 분석

# 예제 데이터 로드
df = load_waltons()  # 실제로는 고객 데이터 사용
print(df.head())
#    T  E    group
# 0  6  1   control
# 1 13  1   control
# 2 13  1   control

# T: 관찰 시간(일, 월 등)
# E: 이벤트 발생 여부(1=이탈, 0=검열)

# Kaplan-Meier Fitter 생성
kmf = KaplanMeierFitter()

# 전체 고객 생존 곡선
kmf.fit(durations=df['T'], event_observed=df['E'])

# 시각화
kmf.plot_survival_function()
plt.title('고객 생존 곡선 (Kaplan-Meier)')
plt.xlabel('시간 (일)')
plt.ylabel('생존 확률 (이탈하지 않을 확률)')
plt.show()

# 중앙 생존 시간 (50% 이탈 시점)
print(f"중앙 생존 시간: {kmf.median_survival_time_}일")

그룹별 비교

# 그룹별 생존 곡선 비교 (예: 유료/무료 사용자)
ax = plt.subplot(111)

for group in df['group'].unique():
    mask = df['group'] == group
    kmf.fit(df[mask]['T'], df[mask]['E'], label=group)
    kmf.plot_survival_function(ax=ax)

plt.title('그룹별 고객 생존 곡선')
plt.xlabel('시간 (일)')
plt.ylabel('생존 확률')
plt.show()

Kaplan-Meier 곡선에서 두 그룹의 생존율이 유의미하게 다른지는 로그 순위 검정(Log-Rank Test)으로 확인할 수 있습니다.

from lifelines.statistics import logrank_test

group_a = df[df['group'] == 'control']
group_b = df[df['group'] == 'treatment']

result = logrank_test(
    group_a['T'], group_b['T'],
    group_a['E'], group_b['E']
)

print(f"p-value: {result.p_value:.4f}")
# p < 0.05면 두 그룹의 생존 곡선이 유의미하게 다름

Cox 비례위험모형: 변수의 영향 분석

Cox 비례위험모형(Cox Proportional Hazards Model)은 여러 독립변수가 생존 시간에 미치는 영향을 분석하는 준모수적 회귀 모델입니다.

위험 함수(Hazard Function)

Cox 모형의 핵심은 위험 함수 h(t)h(t)입니다:

h(tX)=h0(t)exp(β1X1+β2X2++βpXp)h(t|X) = h_0(t) \exp(\beta_1 X_1 + \beta_2 X_2 + \cdots + \beta_p X_p)

  • h(tX)h(t|X): 시점 tt에서 공변량 XX를 가진 개체의 위험(이탈 위험)
  • h0(t)h_0(t): 기저 위험 함수 (모든 공변량이 0일 때의 위험)
  • βi\beta_i: 회귀 계수 (변수의 영향력)
  • XiX_i: 독립변수 (나이, 사용 빈도, 가격 등)

위험비(Hazard Ratio, HR)exp(βi)\exp(\beta_i)로 계산됩니다:
– HR > 1: 변수가 증가하면 이탈 위험 증가
– HR < 1: 변수가 증가하면 이탈 위험 감소
– HR = 1: 변수가 이탈에 영향 없음

실습: 고객 이탈 예측 모델

# 예제 데이터 생성 (실제로는 고객 데이터 사용)
data = pd.DataFrame({
    'duration': [5, 6, 6, 2.5, 4, 12, 8, 10, 14, 16],
    'event': [1, 1, 0, 1, 1, 0, 1, 1, 0, 0],  # 1=이탈
    'age': [25, 32, 45, 28, 35, 50, 29, 38, 42, 55],
    'monthly_usage': [120, 85, 200, 50, 90, 250, 60, 180, 220, 300],
    'price_plan': [1, 1, 2, 1, 1, 2, 1, 2, 2, 2]  # 1=기본, 2=프리미엄
})

# Cox 모델 피팅
cph = CoxPHFitter()
cph.fit(data, duration_col='duration', event_col='event')

# 결과 출력
cph.print_summary()

# 주요 결과 해석
print("\n=== 위험비 (Hazard Ratio) ===")
print(cph.hazard_ratios_)
# age: 0.95 → 나이 1세 증가 시 이탈 위험 5% 감소
# monthly_usage: 0.98 → 사용량 1단위 증가 시 이탈 위험 2% 감소
# price_plan: 0.30 → 프리미엄 플랜 사용자는 이탈 위험 70% 감소

결과 시각화

# 회귀 계수 시각화
cph.plot()
plt.title('Cox 모형 회귀 계수 (95% 신뢰구간)')
plt.show()

# 개별 고객 생존 곡선 예측
new_customer = pd.DataFrame({
    'age': [30],
    'monthly_usage': [100],
    'price_plan': [1]
})

survival_func = cph.predict_survival_function(new_customer)
survival_func.plot()
plt.title('신규 고객 예측 생존 곡선')
plt.xlabel('시간 (월)')
plt.ylabel('생존 확률')
plt.show()

모델 검증: 비례위험 가정 확인

Cox 모형은 비례위험 가정을 전제로 합니다. 즉, 시간에 따라 변수의 영향(위험비)이 일정해야 합니다.

from lifelines.statistics import proportional_hazard_test

# 비례위험 가정 검정
result = proportional_hazard_test(cph, data, time_transform='rank')
print(result)

# p-value > 0.05면 가정 만족
# p-value < 0.05면 가정 위반 → 시간 의존 변수 모델 고려

실무 활용 시나리오

1. 고객 이탈 예측 및 개입 전략

# 이탈 위험 점수 계산
data['churn_risk'] = 1 - cph.predict_survival_function(
    data[['age', 'monthly_usage', 'price_plan']]
).iloc[-1]  # 마지막 시점 생존 확률

# 고위험 고객 추출 (상위 20%)
high_risk = data.nlargest(int(len(data) * 0.2), 'churn_risk')
print("고위험 고객:")
print(high_risk[['age', 'monthly_usage', 'churn_risk']])

2. A/B 테스트 효과 분석

# 쿠폰 제공 그룹 vs 대조군 생존 곡선 비교
kmf = KaplanMeierFitter()

for group in ['control', 'coupon']:
    mask = data['test_group'] == group
    kmf.fit(data[mask]['duration'], data[mask]['event'], label=group)
    kmf.plot_survival_function()

plt.title('쿠폰 제공 효과 분석')
plt.show()

마무리

생존분석은 시간이벤트를 동시에 고려하는 강력한 분석 기법입니다. 특히 검열 데이터를 다룰 수 있어 실무에서 매우 유용합니다.

핵심 요약:
Kaplan-Meier: 검열 데이터를 고려한 생존 곡선 추정, 그룹 비교에 적합
Cox 비례위험모형: 여러 변수의 영향 분석, 위험비로 해석 용이
lifelines: Python에서 생존분석을 쉽게 구현할 수 있는 라이브러리
실무 활용: 고객 이탈 예측, A/B 테스트 분석, 개입 전략 수립

고객 이탈, 기계 고장, 재구매 등 언제 발생할지 모르는 이벤트를 예측해야 한다면 생존분석을 적극 활용해보세요!

Did you find this helpful?

☕ Buy me a coffee

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

TODAY 399 | TOTAL 2,622