온라인 리테일 분석¶
RFM 기반 고객 세분화 및 LTV 분석 프로젝트
개요¶
영국 온라인 리테일 데이터를 활용한 고객 행동 분석 프로젝트. 이벤트 제품을 판매하는 업체의 거래 데이터를 기반으로 고객 세분화, 매출 패턴 분석, 이탈 예측을 수행했다.
- 수행 기간: 프로그래머스 데브코스 4기
- 데이터 출처: Kaggle Online Retail II UCI
- 블로그: 온라인 리테일 분석
문제정의¶
온라인 리테일 시장의 경쟁이 심화되면서 지속 가능한 성장을 위한 명확한 전략이 필요하다.
핵심 질문: 1. 충성도 높은 고객을 어떻게 식별할 것인가? 2. 매출 증대를 위한 핵심 패턴은 무엇인가? 3. 효과적인 마케팅 전략을 어떻게 수립할 것인가?
가설설정¶
가설 1: RFM 분석을 통한 고객 분류¶
- 세부 1-1: 최근에, 자주, 많이 구매한 고객일수록 핵심 충성 고객
- 세부 1-2: 과거 구매 이력이 있지만 최근 활동이 없는 고객은 이탈 위험군
가설 2: 시간대/요일별 매출 집중¶
- 세부 2-1: 평일 점심시간, 특정 요일(목요일)에 주문량 최대
- 세부 2-2: 주말에는 주문 건수가 적어도 평균 주문 금액이 높음
가설 3: 국가별 구매 행동 차이¶
- 세부 3-1: 영국 외 국가 고객은 주문 건수는 적지만 구매 단가가 높음
데이터¶
데이터셋 구조¶
| 컬럼 | 설명 |
|---|---|
| Invoice | 송장 번호 (C로 시작하면 취소) |
| StockCode | 상품 코드 |
| Description | 상품 설명 |
| Quantity | 수량 |
| InvoiceDate | 거래 일시 |
| Price | 단가 |
| Customer ID | 고객 ID |
| Country | 국가 |
전처리¶
# 날짜 데이터 전처리
df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'])
df["InvoiceYear"] = df["InvoiceDate"].dt.year
df["InvoiceMonth"] = df["InvoiceDate"].dt.month
df["InvoiceDay"] = df["InvoiceDate"].dt.day
df["InvoiceDow"] = df["InvoiceDate"].dt.dayofweek
# 매출 데이터 생성
df['TotalPrice'] = df['Quantity'] * df['Price']
# 취소 데이터 분류
df["Cancel"] = df["Quantity"] < 0
cancel_data = df[df['Invoice'].str.contains('C', case=False)]
# 결측치 확인
# Description: 4,382건 - 가격 0으로 매출 무관
# Customer ID: 243,007건 - 비회원 구매로 처리
분석/모델링¶
RFM 분석¶
고객을 Recency(최근성), Frequency(구매 빈도), Monetary(구매액) 기준으로 분류.
rfm["RecencyScore"] = pd.qcut(rfm['Recency'], 5, labels=[5, 4, 3, 2, 1])
rfm["FrequencyScore"] = pd.qcut(rfm['Frequency'].rank(method="first"), 5, labels=[1, 2, 3, 4, 5])
rfm["MonetaryScore"] = pd.qcut(rfm['Monetary'], 5, labels=[1, 2, 3, 4, 5])
rfm["RFM_SCORE"] = (rfm['RecencyScore'].astype(str) +
rfm['FrequencyScore'].astype(str) +
rfm['MonetaryScore'].astype(str))
세그먼트 정의¶
| 세그먼트 | R-F 점수 | 설명 |
|---|---|---|
| Champions | 5[4-5] | 최근 자주 구매하는 최우수 고객 |
| Loyal_Customers | [3-4][4-5] | 충성 고객 |
| Potential_Loyalists | [4-5][2-3] | 잠재적 충성 고객 |
| New_Customers | 51 | 최근 첫 구매 고객 |
| Promising | 41 | 유망 고객 |
| Need_Attention | 33 | 주의 필요 고객 |
| About_to_Sleep | 3[1-2] | 이탈 직전 고객 |
| At_Risk | [1-2][3-4] | 이탈 위험 고객 |
| Cant_Loose | [1-2]5 | 잃으면 안 되는 고객 |
| Hibernating | [1-2][1-2] | 휴면 고객 |
LTV 분석¶
# LTV 계산
ltv = arppu / churn_rate
# ARPPU: 결제 유저당 평균 매출
repeat_customers = rfm[rfm['Frequency'] > 1]
total_revenue = repeat_customers['Monetary'].sum()
arppu = total_revenue / repeat_customers.shape[0]
# Churn Rate: 이탈률
churn_customers = rfm[rfm['Recency'] > rfm['Recency'].quantile(0.8)]
churn_rate = churn_customers.shape[0] / rfm.shape[0]
시계열 예측 (Prophet)¶
from prophet import Prophet
pro = Prophet()
pro.fit(daily_sales_new)
future = pro.make_future_dataframe(periods=365)
forecast = pro.predict(future)
결과¶
시각화¶

요일별 송장(Invoice) 발행 건수 - 토요일 휴무, 평일(월~목) 거래 집중

재구매 고객(상단)과 이탈 고객(하단)의 월별 추이

시간대별 주문 건수 - 10시~15시 피크, 12~14시 최대

Prophet 모델을 활용한 매출 시계열 예측 (신뢰구간 포함)
가설 1 검증 결과¶
- 반복 구매 고객은 8월~11월에 증가
- 이탈 고객은 2010년 10~11월 최대치 후 지속 감소
- 이탈률 감소 추세로 LTV 증가 확인
가설 2 검증 결과¶
- 매출 피크: 점심시간(12시), 목요일
- 주말 평균 매출액: 평일 대비 약 47% 높음
- 11~12월 시즌 매출 급증, 1월 급감
가설 3 검증 결과¶
- 고가 제품(상위 25%): 전체 매출의 40% 기여
- 저가 제품(하위 25%): 매출 기여 20.5%
- 네덜란드: 2011년 후반기부터 매출 기여도 증가
취소 데이터 분석¶
- 전체 매출 대비 취소 비율: 약 7.9%
- 취소 집중 시기: 연말 시즌, 매월 초중반(1~15일)
- 취소 집중 시간: 오전 10시~오후 2시
- 취소 품목 특징: 대부분 단가 1~10 파운드 저가 상품
배운 점¶
- RFM 세그먼트 설정: 너무 세분화하면 실용성 저하, 적정 수준 유지 필요
- LTV 공식 선택: 비즈니스 특성에 맞는 공식 선택이 중요
- 시계열 분석: YoY/MoM은 과거 분석에 한계, Prophet으로 미래 예측 보완
- 취소 데이터 활용: 리텐션 전략 수립에 취소 패턴 분석 필수
기술 스택¶
| 분류 | 도구 |
|---|---|
| 언어 | Python |
| 분석 | pandas, numpy |
| 시각화 | matplotlib, seaborn |
| 시계열 | Prophet |
| 환경 | Jupyter Notebook |