Files
ds_new_user_analy/retention_analysis.md
Gnill82 174e41c5b7 리텐션 분석 스크립트 최초 커밋
Add retention analysis configuration file
- Introduced `retention_analysis_config.json` to define settings for retention analysis.
- Configured analysis settings including correlation threshold, top features, and minimum sample size.
- Specified retention groups for analysis.
- Listed columns to be excluded from the analysis.
- Defined key metrics for day 0 analysis.
- Set output preferences for saving results in various formats.
2025-08-30 21:21:35 +09:00

556 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Retention Analysis Script Documentation
## 개요
`retention_analysis.py`는 던전 스토커즈 게임의 신규 유저 리텐션 분석을 위한 고도화된 Python 분석 도구입니다. 이 스크립트는 통계적 방법론을 기반으로 신규 유저의 행동 패턴을 심층 분석하여 리텐션에 영향을 미치는 핵심 지표를 식별하고, 특히 D0(첫날) 이탈 문제에 대한 실행 가능한 인사이트를 제공합니다.
## 프로젝트 배경 및 필요성
현재 던전 스토커즈는 **D0 이탈률이 65.9%**로 매우 높아 서비스 지속성에 심각한 위협이 되고 있습니다. 모바일 게임 업계 평균 D0 이탈률이 25-35%인 점을 고려하면, 이는 즉각적인 개선이 필요한 critical 수준입니다.
이 스크립트는 데이터 기반의 과학적 접근을 통해:
- **리텐션 영향 요인 정량화**: 어떤 지표가 유저 리텐션에 긍정적/부정적 영향을 미치는지 통계적으로 검증
- **행동 패턴 차이 분석**: D0 이탈 유저와 잔존 유저의 게임 내 행동 패턴의 핵심 차이점 파악
- **개선 우선순위 제시**: 게임 디자인 개선을 위한 데이터 기반의 구체적이고 실행 가능한 인사이트 제공
- **예측 모델 구축**: 머신러닝을 활용한 이탈 위험 예측 및 조기 경보 시스템
## 설치 및 환경 설정
### 필수 패키지 설치
```bash
# 기본 데이터 분석 패키지
pip install pandas numpy scipy matplotlib seaborn
# 머신러닝 패키지
pip install scikit-learn
# 진행률 표시 및 유틸리티
pip install tqdm
# 선택적: 고급 분석을 위한 추가 패키지
pip install plotly jupyter ipywidgets # 인터랙티브 시각화
pip install statsmodels # 고급 통계 분석
```
### 프로젝트 구조
```
ds_new_user_analy/
├── retention_analysis.py # 메인 분석 스크립트 (562 lines)
├── retention_analysis_config.json # 설정 파일 (분석 파라미터 관리)
├── retention_analysis.md # 이 문서 (사용법 및 이론)
└── analysis_results/ # 분석 결과 저장 디렉토리
├── correlation_analysis_YYYYMMDD_HHMMSS.csv # 상관관계 분석 결과
├── d0_churn_analysis_YYYYMMDD_HHMMSS.csv # D0 이탈 분석 결과
├── feature_importance_YYYYMMDD_HHMMSS.csv # 특성 중요도 분석 결과
├── insights_report_YYYYMMDD_HHMMSS.html # HTML 인사이트 리포트
└── retention_analysis_YYYYMMDD_HHMMSS.log # 상세 실행 로그
```
## 사용법
### 기본 실행
```bash
# 명령행 인자로 CSV 파일 지정
python retention_analysis.py path/to/your/analysis_data.csv
# 대화형 모드 (파일 경로 입력 프롬프트)
python retention_analysis.py
```
### 실행 예시
```bash
# 절대 경로 사용 (권장)
python retention_analysis.py "E:\DS_Git\ds_new_user_analy\analysis_results\ds-new_user_analy-20250830_174158.csv"
# 상대 경로 사용
python retention_analysis.py analysis_results/ds-new_user_analy-20250830_174158.csv
```
### 입력 데이터 요구사항
스크립트가 정상 작동하기 위해 CSV 파일에 다음 컬럼들이 필수로 포함되어야 합니다:
**필수 컬럼:**
- `uid`: 사용자 고유 식별자
- `retention_status`: 리텐션 상태 (Retained_d0, Retained_d1, ..., Retained_d7+)
- `create_time`: 사용자 생성 시간 (ISO 8601 형식: `2025-08-13T20:14:43+09:00`)
**권장 컬럼 (분석 품질 향상):**
- `tutorial_complete`: 튜토리얼 완료 여부
- `level_up_count`: 레벨업 횟수
- `play_time_total`: 총 플레이 시간
- `COOP_entry_count`, `Solo_entry_count`: 게임 모드별 진입 횟수
- `death_Monster`, `death_Trap`, `death_PK`: 사망 원인별 통계
- `item_gain_Equipment`, `gold_gain_total`: 아이템/골드 획득량
**데이터 형식 표준:**
- `create_time`은 ISO 8601 표준 형식을 사용하며 빈 값이 없음을 보장
- 한국 시간대(+09:00) 정보를 포함하여 정확한 시간대 분석 지원
- 모든 날짜/시간 계산은 한국 표준시(KST) 기준으로 처리
## 스크립트 작동 원리 및 아키텍처
### 전체 워크플로우
```mermaid
flowchart TD
A[CSV 파일 로드] --> B[데이터 유효성 검사]
B --> C[분석 기간 정보 추출 ISO8601]
C --> D[기본 전처리 및 인코딩]
D --> E[상관관계 분석 Spearman]
E --> F[D0 이탈자 특성 분석 t-test]
F --> G[Feature Importance Random Forest]
G --> H[HTML 인사이트 리포트 생성]
H --> I[결과 파일 저장 CSV/HTML/LOG]
C --> J[시간대별 가입 패턴 분석]
C --> K[요일별 가입 패턴 분석]
J --> H
K --> H
```
### 핵심 클래스: RetentionAnalyzer
```python
class RetentionAnalyzer:
"""
리텐션 분석의 메인 엔진
- 통계적 방법론 적용
- 결과 저장 및 시각화
- 확장 가능한 분석 프레임워크
"
# 핵심 메서드들
def __init__(csv_path, config_path='retention_analysis_config.json') # 초기화
def validate_csv() # 입력 데이터 검증
def load_data() # 데이터 로드 및 기본 통계
def extract_analysis_period() # 분석 기간 및 가입 패턴 추출 (ISO 8601)
def analyze_correlations() # Spearman 상관관계 분석
def analyze_d0_churners() # D0 이탈자 vs 잔존자 비교 (t-test)
def feature_importance_analysis() # Random Forest 중요도 분석
def generate_insights_report() # HTML 리포트 생성 (콘솔로그 제외)
def run_full_analysis() # 전체 분석 파이프라인 실행
```
### 데이터 구조 및 전처리
**1. Retention Status 순서형 인코딩:**
```python
# 문자열 리텐션 상태를 순서형 수치로 변환
retention_groups = ['Retained_d0', 'Retained_d1', ..., 'Retained_d7+']
df['retention_encoded'] = df['retention_status'].map(
{status: i for i, status in enumerate(retention_groups)}
)
# 결과: Retained_d0=0, Retained_d1=1, ..., Retained_d7+=7
```
이 인코딩을 통해 리텐션 단계 간의 순서 관계를 보존하면서 수치 분석이 가능해집니다.
**2. 분석 기간 정보 추출 (create_time 기반):**
```python
# ISO 8601 형식 시간 데이터 처리
create_times = pd.to_datetime(df['create_time'], format='ISO8601')
# 한국 시간대 기준 분석
korea_dates = create_times.dt.tz_convert('Asia/Seoul').dt.date
korea_hours = create_times.dt.tz_convert('Asia/Seoul').dt.hour
korea_weekdays = create_times.dt.tz_convert('Asia/Seoul').dt.dayofweek
# 가입 패턴 분석
daily_signups = korea_dates.value_counts().sort_index() # 일별 가입자
hourly_signups = korea_hours.value_counts().sort_index() # 시간대별 가입자
weekday_signups = korea_weekdays.value_counts().sort_index() # 요일별 가입자
```
**3. 결측값 처리 전략:**
- **상관관계 분석**: 각 지표별로 pairwise deletion (해당 지표만 결측값 제거)
- **Feature Importance**: Zero imputation (게임 내 활동 없음으로 해석)
- **그룹 비교**: Complete case analysis (양쪽 그룹 모두 유효한 값만 사용)
- **시간 데이터**: ISO 8601 표준으로 완전한 데이터 보장
## 통계적 분석 방법론
### 1. 상관관계 분석 (Spearman Rank Correlation)
**목적**: 각 게임 내 지표와 리텐션 단계 간의 단조 관계를 정량화
**왜 Spearman을 선택했는가?**
- `retention_status`가 순서형 변수 (d0 < d1 < d2 < ... < d7+)
- 비모수적 방법으로 분포 가정이 불필요
- 이상치에 민감
- 비선형 단조 관계도 감지 가능
**수학적 배경:**
Spearman 상관계수 ρ는 다음과 같이 계산됩니다:
```
ρ = 1 - (6 × Σd²) / (n × (n² - 1))
```
여기서:
- d: 관측값의 변수 순위 차이
- n: 샘플 크기
**코드 구현:**
```python
from scipy.stats import spearmanr
for col in numeric_columns:
# 결측값 제거
valid_data = df[[col, 'retention_encoded']].dropna()
# 최소 샘플 크기 확인 (기본값: 10)
if len(valid_data) >= min_sample_size:
corr, p_value = spearmanr(
valid_data[col],
valid_data['retention_encoded']
)
# 통계적 유의성 검정 (α = 0.05)
is_significant = p_value < 0.05
```
**결과 해석:**
- ρ > 0: 해당 지표 값이 높을수록 더 오래 게임 플레이 (긍정적)
- ρ < 0: 해당 지표 값이 높을수록 빨리 이탈 (부정적)
- |ρ| > 0.3: 중간 정도의 관계
- |ρ| > 0.5: 강한 관계
### 2. 그룹 비교 분석 (Welch's t-test)
**목적**: D0 이탈 그룹과 잔존 그룹 간의 평균 차이를 통계적으로 검정
**Welch's t-test를 선택한 이유:**
- 등분산성 가정이 불필요 (두 그룹의 분산이 달라도 됨)
- 샘플 크기가 달라도 안정적
- 게임 데이터에서 흔히 발생하는 이분산성 문제 해결
**통계적 가설:**
- H₀(귀무가설): μ₁ = μ₂ (두 그룹의 평균이 같다)
- H₁(대립가설): μ₁ ≠ μ₂ (두 그룹의 평균이 다르다)
**코드 구현:**
```python
from scipy import stats
# D0 이탈자와 잔존자 데이터 분리
d0_users = df[df['retention_status'] == 'Retained_d0']
retained_users = df[df['retention_status'] != 'Retained_d0']
for metric in key_metrics:
d0_data = d0_users[metric].dropna()
retained_data = retained_users[metric].dropna()
# Welch's t-test 수행
t_stat, p_value = stats.ttest_ind(
d0_data,
retained_data,
equal_var=False # 등분산 가정 안 함
)
# 실용적 차이 계산 (효과 크기)
d0_mean = d0_data.mean()
retained_mean = retained_data.mean()
diff_percentage = ((retained_mean - d0_mean) / (d0_mean + 0.0001)) * 100
```
**결과 해석:**
- p-value < 0.05: 통계적으로 유의한 차이 존재
- 차이율 100% 이상: 잔존자가 이탈자보다 2배 이상 높은 지표
- Cohen's d 효과 크기: |d| > 0.8 (큰 효과), 0.5-0.8 (중간), 0.2-0.5 (작은 효과)
### 3. 특성 중요도 분석 (Random Forest)
**목적**: 다변량 환경에서 리텐션 예측에 가장 중요한 변수들을 식별
**Random Forest의 장점:**
- **비선형 관계 포착**: 복잡한 게임 내 상호작용 모델링
- **변수 간 상호작용**: A와 B의 조합 효과 자동 탐지
- **과적합 방지**: 배깅과 랜덤 서브스페이스 기법 사용
- **안정성**: 아웃라이어에 견고함
- **해석 가능성**: 각 변수의 기여도 정량화
**중요도 계산 원리:**
각 변수의 중요도는 해당 변수가 모든 트리에서 불순도 감소에 기여한 평균값입니다:
```
Importance(v) = (1/T) × Σ[t=1 to T] Σ[s∈Splits(v,t)] p(s) × ΔI(s)
```
여기서:
- T: 트리 개수
- p(s): 분할 s에 도달하는 샘플 비율
- ΔI(s): 분할 s에서의 불순도 감소량
**코드 구현:**
```python
from sklearn.ensemble import RandomForestClassifier
# 데이터 준비
X = df[feature_columns].fillna(0) # Zero imputation
y = df['retention_encoded'] # 타겟 변수
# Random Forest 모델 설정
rf = RandomForestClassifier(
n_estimators=100, # 트리 개수 (안정성과 성능 균형)
random_state=42, # 재현 가능성
n_jobs=-1, # 병렬 처리
max_depth=None, # 트리 깊이 제한 없음 (자연스러운 중단)
min_samples_split=2, # 최소 분할 샘플 수
min_samples_leaf=1 # 최소 리프 샘플 수
)
# 모델 학습
rf.fit(X, y)
# 중요도 추출
importance_scores = rf.feature_importances_
```
**결과 해석:**
- 0.1 이상: 매우 중요한 변수 (핵심 개선 타겟)
- 0.05-0.1: 중요한 변수 (보조 개선 요소)
- 0.01-0.05: 보통 중요 (모니터링 지표)
- 0.01 미만: 낮은 중요도 (우선순위 후순위)
## 고급 분석 기법 및 확장
### 1. 통계적 검증 강화
**다중 비교 문제 해결:**
```python
from statsmodels.stats.multitest import multipletests
# Bonferroni 또는 FDR 보정 적용
p_values = [result['p_value'] for result in analysis_results]
rejected, p_corrected, _, _ = multipletests(p_values, method='fdr_bh')
```
**효과 크기 계산:**
```python
# Cohen's d 계산
def cohens_d(group1, group2):
pooled_std = np.sqrt(((len(group1) - 1) * group1.var() +
(len(group2) - 1) * group2.var()) /
(len(group1) + len(group2) - 2))
return (group1.mean() - group2.mean()) / pooled_std
```
### 2. 심층 세그멘테이션 분석
**클러스터링 기반 유저 타입 분류:**
```python
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# 특성 정규화
scaler = StandardScaler()
scaled_features = scaler.fit_transform(df[numeric_columns])
# K-means 클러스터링
kmeans = KMeans(n_clusters=5, random_state=42)
df['user_segment'] = kmeans.fit_predict(scaled_features)
# 세그먼트별 리텐션 패턴 분석
segment_retention = df.groupby(['user_segment', 'retention_status']).size()
```
### 3. 시계열 분석 및 트렌드
**일별/주별 리텐션 트렌드:**
```python
# 코호트 분석
df['signup_date'] = pd.to_datetime(df['signup_date'])
df['cohort'] = df['signup_date'].dt.to_period('W') # 주간 코호트
cohort_retention = df.groupby('cohort')['retention_encoded'].describe()
```
## 설정 파일 상세 설명
### retention_analysis_config.json
```json
{
"analysis_settings": {
"correlation_threshold": 0.05, // 통계적 유의수준 (Type I 오류율)
"top_n_features": 20, // 결과 표시할 상위 중요 변수 개수
"min_sample_size": 10, // 분석 최소 샘플 크기 (신뢰성 확보)
"effect_size_threshold": 0.1 // 실용적 유의성 최소 효과 크기
},
"retention_groups": [ // 리텐션 단계 정의 및 순서
"Retained_d0", "Retained_d1", "Retained_d2", "Retained_d3",
"Retained_d4", "Retained_d5", "Retained_d6", "Retained_d7+"
],
"exclude_columns": [ // 분석에서 제외할 메타데이터 컬럼
"uid", "retention_status", "retention_encoded",
"country", "nickname", "auth_id", "create_time"
],
"key_metrics_for_d0_analysis": [ // D0 분석 핵심 지표 (도메인 지식 기반)
"tutorial_complete", // 온보딩 완료도
"level_up_count", // 성장 경험
"play_time_total", // 참여도
"COOP_entry_count", "Solo_entry_count", // 게임 모드 선호
"death_Monster", "death_Trap", "death_PK", // 실패 경험
"item_gain_Equipment", "gold_gain_total" // 보상 경험
],
"output_settings": {
"save_csv": true, // 원시 데이터 CSV 저장
"save_html": true, // HTML 리포트 저장 (기본 출력)
"save_console_log": true, // 디버깅용 로그 저장
"timestamp_format": "%Y%m%d_%H%M%S" // 파일명 타임스탬프 형식
}
}
```
## 출력 결과 해석 가이드
### 상관관계 분석 결과
**긍정적 상관관계 (양의 값) 해석:**
```
shop_sell_count: 0.428 (p < 0.001)
```
→ 아이템 판매 활동이 활발한 유저일수록 더 오래 게임을 플레이하는 경향
**액션 아이템**: 거래 시스템 개선, 마켓플레이스 UX 향상
**부정적 상관관계 (음의 값) 해석:**
```
dungeon_first_result: -0.173 (p < 0.01)
```
→ 첫 던전에서 실패한 유저일수록 빨리 이탈하는 경향
**액션 아이템**: 초심자 던전 난이도 조정, 실패 시 보상 시스템
### Feature Importance 결과
**중요도 점수별 액션:**
- **0.1 이상** (매우 중요): 즉시 개선 프로젝트 착수
- **0.05-0.1** (중요): 다음 분기 개선 계획에 포함
- **0.01-0.05** (보통): 정기 모니터링 대상
- **0.01 미만** (낮음): 우선순위 후순위
### D0 분석 결과
**차이율별 해석 및 액션:**
```
tutorial_complete:
- D0 평균: 0.23, 잔존 평균: 0.89, 차이: 287%
```
→ 튜토리얼 완료가 리텐션에 결정적 영향
**즉시 액션**: 튜토리얼 완료율 개선 프로젝트
### 가입 패턴 분석 결과
**시간대별 분석:**
```
가입 집중 시간: 20시 (1,250명)
```
→ 저녁 시간대에 가입이 집중됨을 의미
**마케팅 액션**: 해당 시간대 타겟팅 광고 집중
**요일별 분석:**
```
가입 집중 요일: 토요일 (3,200명)
```
→ 주말에 신규 가입이 활발함
**운영 액션**: 주말 이벤트 및 서버 안정성 강화
## 문제 해결 및 최적화
### 일반적인 오류와 해결책
**1. 메모리 부족 오류**
```python
# 청크 단위 처리
chunk_size = 50000
for chunk in pd.read_csv(filepath, chunksize=chunk_size):
process_chunk(chunk)
```
**2. 인코딩 오류**
```python
# UTF-8 인코딩 명시적 지정
df = pd.read_csv(filepath, encoding='utf-8-sig')
```
**3. 성능 최적화**
```python
# 데이터 타입 최적화
df['user_level'] = df['user_level'].astype('int16') # 메모리 절약
df['is_premium'] = df['is_premium'].astype('bool') # 불린 최적화
```
### 대용량 데이터 처리
**샘플링 전략:**
```python
# 층화 샘플링 (각 리텐션 그룹에서 동일 비율 추출)
from sklearn.model_selection import train_test_split
sampled_data, _ = train_test_split(
df,
test_size=0.7, # 30%만 사용
stratify=df['retention_status'], # 층화
random_state=42
)
```
## 비즈니스 임팩트 및 ROI
### 개선 우선순위 매트릭스
```
높은 임팩트 낮은 임팩트
높은 구현비용 [계획 검토] [보류]
낮은 구현비용 [즉시 실행] [빠른 승리]
```
### A/B 테스트 설계
분석 결과를 바탕으로 한 개선안은 반드시 A/B 테스트를 통해 검증:
```python
# 실험 설계 예시
control_group = new_users.sample(frac=0.5, random_state=42)
treatment_group = new_users.drop(control_group.index)
# 개선 효과 측정
improvement = (treatment_retention - control_retention) / control_retention
statistical_power = calculate_power(effect_size, alpha=0.05, sample_size=len(control_group))
```
## 결론 및 향후 개선
`retention_analysis.py` 스크립트는 단순한 데이터 분석을 넘어서, 게임 서비스 개선을 위한 **의사결정 지원 시스템**의 역할을 합니다.
**핵심 가치:**
1. **과학적 접근**: 통계적으로 검증된 방법론으로 신뢰할 수 있는 인사이트 제공
2. **실행 가능성**: 분석 결과가 구체적인 개선 액션으로 연결
3. **확장성**: 새로운 분석 기법과 지표를 쉽게 추가 가능
4. **자동화**: 정기적인 분석과 모니터링을 통한 지속적 개선
5. **시간대 인사이트**: 가입 패턴 분석으로 마케팅/운영 최적화 지원
**2024년 8월 업데이트 내용:**
- **HTML 리포트**: 마크다운에서 전문적인 HTML 형식으로 변경
- **분석 기간 정보**: ISO 8601 형식 `create_time` 기반 자동 추출
- **시간대 분석**: 한국 시간 기준 시간대별/요일별 가입 패턴 분석
- **콘솔로그 분리**: HTML 리포트에서 콘솔로그 제거, 상세 분석 데이터 중심으로 개편
- **데이터 품질 강화**: 표준 시간 형식 지원으로 분석 정확도 향상
**향후 발전 방향:**
- 실시간 대시보드 연동 (가입 패턴 실시간 모니터링)
- 예측 모델 고도화 (딥러닝 활용)
- 개인화된 리텐션 전략 추천 (시간대별 타겟팅)
- 자동화된 A/B 테스트 파이프라인
- 가입 패턴 기반 마케팅 최적화 시스템
정기적인 분석을 통해 게임 개선 효과를 측정하고, 새로운 문제점을 조기에 발견하여 서비스의 지속 가능한 성장에 기여할 수 있습니다.