생존분석이란?
생존분석(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 모형의 핵심은 위험 함수 입니다:
- : 시점 에서 공변량 를 가진 개체의 위험(이탈 위험)
- : 기저 위험 함수 (모든 공변량이 0일 때의 위험)
- : 회귀 계수 (변수의 영향력)
- : 독립변수 (나이, 사용 빈도, 가격 등)
위험비(Hazard Ratio, HR)는 로 계산됩니다:
– 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
Leave a Reply