2025년 2학기 계량분석 강의 계획

15주차: 군집분석

1. 군집분석의 이론적 이해


1. 군집분석 개요 및 목적

👉 **요인분석**은 변수를 묶는 분석, **군집분석**은 대상을 묶는 분석이라는 점을 구분해 강조


2. 군집분석 자료의 조건


3. 유사성 측정 방법

  • **군집분석**: 유사한 대상을 그룹화하는 기법
  • **요인분석과 차이점**: 요인분석은 변수를 묶음, 군집분석은 대상을 묶음
  • **자료 조건**: 등간·비율척도 자료, 표준화 필수
  • **유사성 측정**: 가장 기본은 **유클리디안 거리**

2. Python 실습: 계층적 군집분석


  • 준비까지 15분: 표준화·링키지·덴드로그램
  • 본 분석 20분: 군집 수 선택·라벨링·프로파일링
  • 평가/비교 15분: 실루엣 점수·연결법 비교·주의사항

A) 덴드로그램 기반 군집 수 고르기 & 라벨 부여


from scipy.cluster.hierarchy import fcluster

# (선택) 덴드로그램의 고도(거리)를 보며 3개 군집으로 가정
k = 3

# 방법 1: 군집 개수로 자르기
labels_k = fcluster(linked, t=k, criterion='maxclust')

# (대안) 방법 2: 거리 기준으로 자르기 (예: 임계값 t_dist)
# labels_dist = fcluster(linked, t=7.0, criterion='distance')

# 라벨 붙이기
df['cluster'] = labels_k
df.head()

시각적으로 “자르는 높이” 보기(색으로 표시)


# 덴드로그램에 color_threshold 표시 (임계값은 데이터에 맞게 조정)
plt.figure(figsize=(10, 7))
dendrogram(linked,
           orientation='top',
           labels=df['고객ID'].tolist(),
           distance_sort='descending',
           show_leaf_counts=True,
           color_threshold=15)   # 예: 높이 15 지점
plt.title('고객 군집화 덴드로그램 (color_threshold 예시)')
plt.xlabel('고객')
plt.ylabel('거리')
plt.show()

B) 군집 프로파일링(해석용 요약표 & 표준화 평균)


# 원척도 기준 요약
profile_raw = df.groupby('cluster')[['나이', '월평균_소득', '월평균_소비']].agg(['mean','median','count'])
print("\n[군집 프로파일(원척도)]")
print(profile_raw)

# 표준화 점수로 각 변수의 상대적 높낮이 비교
X_scaled_df = pd.DataFrame(X_scaled, columns=X.columns)
X_scaled_df['cluster'] = labels_k

profile_std = X_scaled_df.groupby('cluster')[['나이','월평균_소득','월평균_소비']].mean().round(2)
print("\n[군집 프로파일(표준화 평균, 0=평균, ±값=평균 대비 편차)]")
print(profile_std)

간단한 레이더/막대 그래프(막대형 예시)


# 군집별 표준화 평균 막대그래프
ax = profile_std.plot(kind='bar', figsize=(8,5))
ax.set_title('군집별 표준화 평균(나이/소득/소비)')
ax.set_xlabel('Cluster')
ax.set_ylabel('표준화 평균')
plt.axhline(0, color='gray', linestyle='--')
plt.tight_layout()
plt.show()

해석 가이드


C) 군집 품질 간단 평가(실루엣 점수)


from sklearn.metrics import silhouette_score

# 계층 군집 라벨로 실루엣 점수 계산(표준화 데이터 사용)
sil = silhouette_score(X_scaled, labels_k, metric='euclidean')
print(f"\n[실루엣 점수] k={k} → {sil:.3f}")

D) 연결법(method)·거리(metric) 비교(선택)


from scipy.spatial.distance import pdist
from scipy.cluster.hierarchy import cophenet

# 다양한 연결법 비교: 'ward'(기본), 'average', 'complete', 'single'
methods = ['ward', 'average', 'complete']
results = []
Y = pdist(X_scaled, metric='euclidean')

for m in methods:
    Zm = linkage(X_scaled, method=m)
    coph_corr, _ = cophenet(Zm, Y)  # 코페네틱 상관계수 (덴드로그램 보존력 지표)
    # 동일 k로 라벨링해 실루엣 점수도 비교
    labels_m = fcluster(Zm, t=k, criterion='maxclust')
    sil_m = silhouette_score(X_scaled, labels_m)
    results.append((m, coph_corr, sil_m))

print("\n[연결법 비교: 코페네틱 상관계수 & 실루엣]")
for m, coph, sil_m in results:
    print(f"method={m:8s}  cophenetic={coph:.3f}  silhouette={sil_m:.3f}")

E) 결과 보고 템플릿(요약 문장 예시)


F) 실습 체크리스트(요약)

3. 군집 결과 해석 및 프로파일링


1. 덴드로그램 해석

👉 해석 포인트:


2. 군집 할당 및 특성 요약


from scipy.cluster.hierarchy import fcluster

# 1. 3개 군집으로 데이터에 군집 할당
num_clusters = 3
df['군집_레이블'] = fcluster(linked, num_clusters, criterion='maxclust')

# 2. 군집별 특성 파악 (평균값 계산)
cluster_profiles = df.groupby('군집_레이블')[['나이', '월평균_소득', '월평균_소비']].mean()

print("\n--- 군집별 평균 특성 ---")
print(cluster_profiles)

3. 군집별 프로파일링 및 명명

예시 해석:

👉 이렇게 명명하면 **타겟팅 전략**을 세울 때 유용

수업 정리

K-means 군집분석 비교 실습


1. 데이터 준비 및 표준화


import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt

# (이전 단계 동일 데이터 사용)
data = {
    '고객ID': range(1, 16),
    '나이': [25, 30, 45, 50, 35, 60, 28, 40, 55, 33, 48, 52, 29, 38, 43],
    '월평균_소득': [300, 350, 500, 550, 400, 650, 320, 450, 600, 380, 520, 580, 310, 420, 480],
    '월평균_소비': [100, 120, 250, 280, 180, 320, 110, 200, 290, 150, 260, 270, 120, 190, 240]
}
df = pd.DataFrame(data)

X = df[['나이', '월평균_소득', '월평균_소비']]
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

2. Elbow Method


inertia = []
K_range = range(1, 8)  # 1~7개 군집 시험

for k in K_range:
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    kmeans.fit(X_scaled)
    inertia.append(kmeans.inertia_)

# Elbow Plot
plt.figure(figsize=(8, 5))
plt.plot(K_range, inertia, marker='o')
plt.title('Elbow Method')
plt.xlabel('군집 수 (k)')
plt.ylabel('Inertia (군집 내 제곱합)')
plt.grid(True)
plt.show()


3. Silhouette Score


sil_scores = {}
for k in range(2, 7):  # 2~6개 군집에 대해 계산
    kmeans = KMeans(n_clusters=k, random_state=42, n_init=10)
    labels = kmeans.fit_predict(X_scaled)
    sil = silhouette_score(X_scaled, labels)
    sil_scores[k] = sil

print("\n--- Silhouette Scores ---")
for k, score in sil_scores.items():
    print(f"k={k}: {score:.3f}")

# 시각화
plt.figure(figsize=(8, 5))
plt.plot(list(sil_scores.keys()), list(sil_scores.values()), marker='o')
plt.title('Silhouette Score by k')
plt.xlabel('군집 수 (k)')
plt.ylabel('Silhouette Score')
plt.grid(True)
plt.show()


4. K-means 군집 실행 및 프로파일링


# 최종 군집 수 (예: 3개)
best_k = 3
kmeans_final = KMeans(n_clusters=best_k, random_state=42, n_init=10)
df['Kmeans_군집'] = kmeans_final.fit_predict(X_scaled)

# 군집별 평균 특성
kmeans_profiles = df.groupby('Kmeans_군집')[['나이', '월평균_소득', '월평균_소비']].mean()

print("\n--- K-means 군집별 평균 특성 ---")
print(kmeans_profiles)

# 시각화 (산점도)
plt.figure(figsize=(8, 6))
plt.scatter(df['월평균_소득'], df['월평균_소비'], c=df['Kmeans_군집'], cmap='viridis', s=100)
plt.xlabel('월평균 소득')
plt.ylabel('월평균 소비')
plt.title('K-means 군집 결과 시각화')
plt.colorbar(label='군집')
plt.show()


5. 결과 해석 및 계층적 군집과 비교

비교 요약

수업 마무리 포인트

4. 질의응답 및 요약


1. 최종 정리

군집분석의 핵심 요약

분석 과정 핵심

  1. **데이터 준비**
    • 변수는 등간/비율척도
    • 단위 차이 보정을 위해 **표준화 필수**
  2. **군집 수 결정**
    • 계층적 군집: **덴드로그램** 해석
    • K-means: **Elbow Method, Silhouette Score**
  3. **군집 해석(프로파일링)**
    • 각 군집의 평균값을 비교 → 의미 있는 이름 부여
    • 예: *저연령-저소득-저소비*, *중년-중간 소비층*, *고연령-고소득 소비층*

방법론 비교


2. 질의응답