온라인 리테일 분석¶
RFM 기반 고객 세분화 및 LTV 분석 프로젝트
개요¶
영국 온라인 리테일 데이터를 활용한 고객 행동 분석 프로젝트. 이벤트 제품을 판매하는 업체의 거래 데이터를 기반으로 고객 세분화, 매출 패턴 분석, 이탈 예측을 수행했다.
- 수행 기간: 프로그래머스 데브코스 4기
- 데이터 출처: Kaggle Online Retail II UCI
- 블로그: 온라인 리테일 분석
문제정의¶
온라인 리테일 시장의 경쟁이 심화되면서 지속 가능한 성장을 위한 명확한 전략이 필요함.
핵심 질문:
- 충성도 높은 고객을 어떻게 식별할 것인가?
- 매출 증대를 위한 핵심 패턴은 무엇인가?
- 효과적인 마케팅 전략을 어떻게 수립할 것인가?
가설설정¶
가설 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))
세그먼트 정의¶
Champions (R-F: 5[4-5]) - 최근 자주 구매하는 최우수 고객
Loyal_Customers (R-F: [3-4][4-5]) - 충성 고객
Potential_Loyalists (R-F: [4-5][2-3]) - 잠재적 충성 고객
New_Customers (R-F: 51) - 최근 첫 구매 고객
Promising (R-F: 41) - 유망 고객
Need_Attention (R-F: 33) - 주의 필요 고객
About_to_Sleep (R-F: 3[1-2]) - 이탈 직전 고객
At_Risk (R-F: [1-2][3-4]) - 이탈 위험 고객
Cant_Loose (R-F: [1-2]5) - 잃으면 안 되는 고객
Hibernating (R-F: [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
관련 문서¶
- RFM 분석 기법
- LTV 분석 기법
- 코호트 분석