# ── 2. 데이터 탐색 ─────────────────────────────────────────────
print()
print("수치형 컬럼 기초 통계:")
#✏️ 수치형 데이터의 요약 통계량 확인
print(df_ecom.describe())
print()
print("회원등급 분포:")
#✏️ 범주형 데이터의 빈도 확인
print(df_ecom['회원등급'].value_counts())
df_ecom.describe()를 사용하여 수치형 데이터의 통계를 전체적으로 살펴봅니다.
이때 여기에서 살펴 볼 수 있는 것은 월평균 구매 금액에서 max와 75%에서 금액 차이가 난다는 것을 볼 수 있고,
쿠폰 사용 평균이 0.7로 쿠폰 사용이 많다는 걸 의미합니다.
(장바구니담기, 리뷰작성, 쿠폰사용 등과 같이 0과 1로 된 값의 경우에는 mean 값을 살펴보길 권장합니다.)
3. 전처리
# ── 3. 전처리 ──────────────────────────────────────────────────
df_ecom_proc = df_ecom.copy()
#✏️ 범주형 컬럼 인코딩 (문자열 -> 숫자)
cat_cols = ['성별', '연령대', '회원등급', '선호카테고리']
le = LabelEncoder()
for col in cat_cols:
#✏️ 각 컬럼별로 LabelEncoding 적용
df_ecom_proc[col] = le.fit_transform(df_ecom_proc[col])
# 분석에 사용할 수치형 특성들 정의
feature_cols = ['성별', '연령대', '회원등급', '선호카테고리', '월평균구매횟수',
'월평균구매금액', '최근구매일_일전', '장바구니담기', '리뷰작성', '쿠폰사용', '앱설치', '재구매']
#✏️ 데이터 스케일링 (거리 기반 모델인 K-Means 필수 과정)
X = df_ecom_proc[feature_cols]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print()
print("전처리(인코딩 + 스케일링) 완료")
성별, 연령대, 회원등급, 선호카테고리의 경우에는 범주형 데이터입니다.
클러스터링을 진행하기 위해서는 범주형 데이터를 수치형 데이터를 변환해야 합니다.
LabelEncoder를 적용하여 수치형 데이터들로 바꿔줍니다.
4. 엘보우 방법 적용
# ── 4. 엘보우 방법 ─────────────────────────────────────────────
#✏️ 클러스터 내 오차제곱합(Inertia) 저장 리스트
inertia_list = []
for k in range(1, 11):
#✏️ KMeans 모델 생성 및 학습
km = KMeans(n_clusters=k, random_state=42, n_init=10)
km.fit(X_scaled)
inertia_list.append(km.inertia_)
plt.figure(figsize=(8, 5))
plt.plot(range(1, 11), inertia_list, 'bo-', linewidth=2, markersize=8)
plt.title('엘보우 방법 - 이커머스 고객 데이터', fontsize=13, fontweight='bold')
plt.xlabel('K (클러스터 수)')
plt.ylabel('Inertia')
plt.xticks(range(1, 11))
plt.grid(True, alpha=0.3)
plt.axvline(x=3, color='red', linestyle='--', linewidth=1.5, label='권장 K=3')
plt.tight_layout()
plt.show()
완만한 지점이 최적의 군집 개수 지점입니다.
너무 많이 분류하게 되면 세분화가 과하게 진행되어, 군집을 나누는 의미가 없어집니다.
즉 클러스터링을 하게 되는 의미가 없어지게 되는데, 이때 inertia 시각화를 하여 완만한 지점을 찾게 되면 그 지점이 최적의 군집 개수 입니다.
5. 모델 학습
# ── 5. 모델 학습 ───────────────────────────────────────────────
#✏️ 엘보우 그래프를 보고 적절한 K 선택 (통상 3으로 설정)
K = 3
kmeans = KMeans(n_clusters=K, random_state=42, n_init=10)
kmeans.fit(X_scaled)
#✏️ 결과 레이블을 원본 데이터프레임에 추가
df_ecom['클러스터'] = kmeans.labels_
print()
print(f"K={K} 군집 분석 완료")
print("클러스터별 인원 수:")
print(df_ecom['클러스터'].value_counts().sort_index())
6. 시각화
# ── 6. 시각화 ──────────────────────────────────────────────────
#✏️ 고차원 데이터를 2차원으로 축소 (시각화용)
pca = PCA(n_components=2, random_state=42)
X_2d = pca.fit_transform(X_scaled)
colors = ['#E05C5C', '#4A90D9', '#52A97A'] # 클러스터 수 K=3에 맞춰 색상 준비
plt.figure(figsize=(9, 6))
#✏️ 각 클러스터별로 산점도 그리기
for i in range(K):
mask = df_ecom['클러스터'] == i
plt.scatter(X_2d[mask, 0], X_2d[mask, 1],
c=colors[i], label=f'클러스터 {i}',
alpha=0.8, s=100, edgecolors='white')
plt.title('이커머스 고객 군집 분석 결과 (PCA)', fontsize=14, fontweight='bold')
plt.xlabel('주성분 1(가장 많은 정보를 담은 축)')
plt.ylabel('주성분 2(두 번째로 많은 정보를 담은 축)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
같은 색의 점들이 뭉쳐져서 멀리 떨어져 있을 수록 잘 군집화된 것입니다.
7. 각 클러스터별 페르소나 설정
# 분석할 클러스터 개수 설정 (앞서 학습한 K값과 동일하게)
K = 3
print(" 각 클러스터별 대표 페르소나 분석 ")
print("=" * 50)
for cluster_id in range(K):
# 해당 클러스터에 속하는 데이터만 필터링
group = df_ecom[df_ecom['클러스터'] == cluster_id]
print(f"[클러스터 {cluster_id}] (인원: {len(group)}명)")
# 범주형 데이터의 최빈값(mode) 추출
# mode()는 Series를 반환하므로 [0]을 통해 가장 빈도가 높은 첫 번째 값을 가져옴
print(f"1. 주요 성별 : {group['성별'].mode()[0]}")
print(f"2. 주요 연령대 : {group['연령대'].mode()[0]}")
print(f"3. 주요 등급 : {group['회원등급'].mode()[0]}")
print(f"4. 선호 카테고리 : {group['선호카테고리'].mode()[0]}")
# 수치형 데이터는 평균(mean)을 사용하는 것이 더 직관적일 수 있습니다
print(f"5. 평균 구매 금액 : {int(group['월평균구매금액'].mean()):,}원")
print(f"6. 평균 구매 횟수 : {group['월평균구매횟수'].mean():.1f}회")
print("-" * 50)
각 클러스터별로 성별, 연령대, 회원등급, 선호카테고리에서 최빈값을 구하여 분석을 진행합니다.
# 분석에 사용할 클러스터 개수 (앞서 설정한 K값)
K = 3
print(" 각 클러스터별 상세 특징 분석 (Profiling) ")
print("=" * 60)
for cluster_id in range(K):
# 1. 원본 데이터와 전처리 데이터를 클러스터별로 필터링
# (원본 df_ecom에 '클러스터' 레이블이 포함되어 있어야 합니다)
group = df_ecom[df_ecom['클러스터'] == cluster_id]
print(f"▶ [클러스터 {cluster_id}] 분석 결과 (인원: {len(group)}명)")
# 2. 범주형 데이터 최빈값 (가장 대표적인 특징)
mode_gender = group['성별'].mode()[0]
mode_age = group['연령대'].mode()[0]
mode_grade = group['회원등급'].mode()[0]
mode_cat = group['선호카테고리'].mode()[0]
# 3. 수치형 데이터 평균 (주요 지표)
avg_spend = group['월평균구매금액'].mean()
avg_count = group['월평균구매횟수'].mean()
avg_recency = group['최근구매일_일전'].mean()
# 4. 행동 지표 비율 (평균값이 곧 수행 비율)
app_rate = group['앱설치'].mean() * 100
coupon_rate = group['쿠폰사용'].mean() * 100
revisit_rate = group['재구매'].mean() * 100
# 출력 부분
print(f" - 대표 페르소나 : {mode_age} {mode_gender} ({mode_grade} 등급)")
print(f" - 선호 카테고리 : {mode_cat}")
print(f" - 평균 구매력 : 월 {int(avg_spend):,}원 / {avg_count:.1f}회")
print(f" - 평균 방문 주기 : 최근 {avg_recency:.1f}일 전 방문")
print(f" - 주요 행동 패턴 : 앱설치({app_rate:.0f}%), 쿠폰사용({coupon_rate:.0f}%), 재구매({revisit_rate:.0f}%)")
print("-" * 60)
상세 특징을 보니 VIP 여성의 경우 뷰티를 선호하며, 다른 페르소나에 비해 많은 돈을 쓰고 있습니다. 재구매도 100퍼센트이며 7일 전에 방문한 점을 보아 놓쳐서 안되는 고객임을 알 수 있습니다.
40대 남성의 경우 실버 등급으로 11만 7천원을 쓰는 고객으로 VIP 등급으로 상승시킬 마케팅 전략을 수립해야함을 알 수 있습니다.
이제 나머지 일반 등급의 경우에는 쿠폰사용이 100퍼센트이고 재구매가 0퍼센트로 쿠폰 사용만 하는 체리피커로 볼 수 있습니다. 체리피커의 경우에는 재구매를 유도하는 방식의 전략이 중요하다고 볼 수 있습니다.
하지만 이 모든 마케팅 전략을 수립하기에 자원이 한정적일 수 있으니, 우선순위를 정해야 해야합니다.
VIP 고객 -> 실버 등급의 40대 남성 -> 일반 (20대 남성)
위와 같이 순서를 정하여 마케팅 전략을 수립하고자 합니다.
8. 마케팅 후속 액션
클러스터 0: "성장 가능성이 높은 실버 그룹" (Target: 40대 남성)
앱도 설치했고 구매력도 중간 수준(11만 원)이지만, 재구매율이 57%로 살짝 애매합니다. 패션 카테고리는 유행에 민감하므로 이탈을 막는 것이 중요합니다.
마케팅 전략: [업셀링(Up-selling) 및 리마인드]
카테고리 확장: 패션 외에 연관된 잡화나 시계 등 단가가 높은 품목을 추천하여 구매 금액을 높이세요.
재방문 트리거: 방문 주기가 24일로 늘어지는 시점에 "찜해둔 상품의 재고가 얼마 남지 않았습니다"와 같은 앱 푸시 알림을 보내세요.
회원 등급 업그레이드 예고: "구매 2회만 더 하시면 골드 등급 혜택을 드립니다"와 같은 챌린지를 부여하세요.
클러스터 1: "쿠폰 사냥꾼 및 이탈 위기군" (Target: 20대 남성)
구매 금액이 낮고, 앱 설치도 안 했으며, 방문 주기가 68일로 매우 깁니다. 하지만 쿠폰 사용률은 100%입니다. 즉, 혜택이 없으면 절대 사지 않는 그룹입니다.
마케팅 전략: [앱 설치 유도 및 효율적 관리]
앱 전용 초저가 딜: "앱 설치 시에만 식품 카테고리 990원" 같은 파격적인 조건을 걸어 일단 앱으로 끌어들여야 합니다. (이후 푸시 알림 타겟팅을 위해)
첫 재구매 유도: 재구매율이 0%입니다. 첫 구매 후 3일 이내에 사용할 수 있는 '감사 쿠폰'을 발행해 두 번째 구매 경험을 강제로 만들어주세요.
리소스 배분: 만약 마케팅 예산이 한정적이라면, 이 그룹에 대한 무차별적인 광고보다는 클러스터 2와 0에 집중하는 것이 매출 기여도 측면에서 훨씬 유리합니다.
클러스터 2: "우리의 보물, 로열 VIP" (Target: 30대 여성)
가장 높은 구매력과 재구매율(100%)을 가진 핵심 그룹입니다. 특징은 쿠폰 사용률이 낮다(36%)는 점인데, 이는 가격보다 브랜드 가치나 편의성을 중시한다는 증거입니다.
마케팅 전략: [락인(Lock-in) 및 VIP 대우]
프라이빗 혜택: 쿠폰 뿌리기보다는 '무료 배송', 'VIP 전용 상담 라인', '신제품 우선 구매권' 같은 특별 대우를 제공하세요.
리뷰 리워드 강화: 이들은 재구매가 활발하므로, 양질의 리뷰를 쓸 확률도 높습니다. 리뷰 작성 시 포인트를 두 배로 주어 커뮤니티 활성화를 유도하세요.
구독 모델 제안: 구매 주기가 7일로 매우 짧으므로 정기 구독 서비스를 제안하기 최적입니다.