# 2025-06-19

rm(list=ls())
ls()
## character(0)
# 군집분석
# 1. 필요한 패키지 설치 및 로드
# install.packages("datasets")  # 기본 설치됨
# install.packages("ggdendro")  # 선택적으로 ggplot2 기반 시각화 가능
library(datasets)
# 2. 데이터 불러오기 (예: USArrests)
data("USArrests")
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
glimpse(USArrests)
## Rows: 50
## Columns: 4
## $ Murder   <dbl> 13.2, 10.0, 8.1, 8.8, 9.0, 7.9, 3.3, 5.9, 15.4, 17.4, 5.3, 2.…
## $ Assault  <int> 236, 263, 294, 190, 276, 204, 110, 238, 335, 211, 46, 120, 24…
## $ UrbanPop <int> 58, 48, 80, 50, 91, 78, 77, 72, 80, 60, 83, 54, 83, 65, 57, 6…
## $ Rape     <dbl> 21.2, 44.5, 31.0, 19.5, 40.6, 38.7, 11.1, 15.8, 31.9, 25.8, 2…
df <- na.omit(USArrests)  # 결측치 제거 (없지만 안전하게 처리)
# 3. 표준화 (스케일링) - 변수 단위 맞추기 위해 꼭 필요!
df_scaled <- scale(df)
# 4. 거리 행렬 계산 (유클리디안 거리)
dist_matrix <- dist(df_scaled, method = "euclidean")
# 5. 계층적 군집분석 수행 (연결 방법: complete linkage)
hc <- hclust(dist_matrix, method = "complete")
# hclust(): 계층적 군집 실행 (method = "complete" 외에도
# "single", "average", "ward.D" 등 가능)
# 6. 덴드로그램 시각화
plot(hc,
     main = "계층적 군집분석 덴드로그램",
     xlab = "",
     sub = "",
     cex = 0.7,
     hang = -1)
# 7. 군집 수 시각적으로 표시 (예: 4개 군집으로 나누기)
rect.hclust(hc, k = 4, border = "blue")

#  계층적 군집분석 with 맨해튼 거리 (R 코드)
# 1. 데이터 불러오기 및 확인
data("USArrests")       
# 내장 데이터셋
df <- na.omit(USArrests)  # 결측치 제거 (실제 데이터에는 없음)
# 2. 데이터 표준화 (스케일 조정)
df_scaled <- scale(df)
# 3. 거리 행렬 계산 - 맨해튼 거리 사용
dist_man <- dist(df_scaled, method = "manhattan")
# 4. 계층적 군집 분석 수행 (Complete linkage 방식)
hc_man <- hclust(dist_man, method = "complete")
# 5. 덴드로그램 시각화
plot(hc_man,
     main = "계층적 군집분석 (맨해튼 거리)",
     xlab = "",
     sub = "",
     cex = 0.7,
     hang = -1)
# 6. 군집 수 시각적 표시 (예: 4개 군집)
rect.hclust(hc_man, k = 4, border = "red")

# 실루엣 계수
# 필요한 패키지 설치
# install.packages("cluster")
# install.packages("factoextra")
# 패키지 로드
library(cluster)
library(factoextra)
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
# 데이터 준비 (iris 데이터에서 품종 제거)
data(iris)
df <- iris[, -5]  # 군집용 수치형 데이터만 사용
# K-평균 군집 수행 (예: K=3)
set.seed(123)
km_result <- kmeans(df, centers = 3, nstart = 25)
# K-평균 알고리즘은 초기 중심점(centroid)을 무작위로 선택
# 초기 위치에 따라 결과가 좋기도 하고, 나쁘기도 합니다.
# 25번 서로 다른 초기화 시도
# 그 중에서 가장 좋은(오차 제곱합 SSE가 가장 낮은) 결과를 선택합니다.
# 군집 결과 확인
km_result$cluster
##   [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
##  [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
##  [75] 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 3 3 3 3 2 3 3 3 3
## [112] 3 3 2 2 3 3 3 3 2 3 2 3 2 3 3 2 2 3 3 3 3 3 2 3 3 3 3 2 3 3 3 2 3 3 3 2 3
## [149] 3 2
# 이 코드를 실행하면:
# df 데이터셋의 각 관측치(행)가
# 군집 번호 1, 2, 3 중 어디에 속하는지
# 그 결과가 벡터 형태로 출력됩니다.
# 실루엣 계수 계산 및 시각화
# 실루엣 계산을 위해 군집 결과를 기반으로 silhouette() 함수 사용
sil <- silhouette(km_result$cluster, dist(df))
# 실루엣 결과 시각화
fviz_silhouette(sil)
##   cluster size ave.sil.width
## 1       1   50          0.80
## 2       2   62          0.42
## 3       3   38          0.45

# 평균 실루엣 계수 (Average silhouette width): 0.55
# 0.5 이상 → 꽤 잘 분리된 군집
# 색상 (빨강, 초록, 파랑) : 군집 번호 (Cluster 1, 2, 3)
# 붉은 점선: 전체 데이터의 평균 실루엣 계수 (0.55) 기준선
#  Cluster 3 (파랑)
# 파란색 군집은 setosa로 의사결정나무에서도 쉽게 구분되는 품종이었음
# 대부분 실루엣 계수가 0.6~0.8 이상
# ▶ 가장 응집력 좋고, 잘 분리된 군집으로 판단
# 결론
# 군집 수(K=3)는 꽤 타당하지만, 더 나은 K가 있을 수도 있음
# k=2일때 실루엣 계수를 계산하시오?
# K-평균 군집 수행 (예: K=3)

set.seed(123)
km_result <- kmeans(df, centers = 2, nstart = 25)
sil <- silhouette(km_result$cluster, dist(df))
# 실루엣 결과 시각화
fviz_silhouette(sil)
##   cluster size ave.sil.width
## 1       1   53          0.77
## 2       2   97          0.63

# 실습 
# datarium 패키지에 포함된 예제 데이터
#변수명       
# 설명
#YouTube    
#Facebook    
#Newspaper  
# YouTube 광고비 (단위: 1000달러)
# Facebook 광고비 (단위: 1000달러)
# 신문광고비 (단위: 1000달러)
#Sales      
# 해당 캠페인의 결과 매출액 (단위: 1000달러)
# 군집 결과가 의미하는 것 (예시)
# Cluster1 : YouTube 비중이 높고, Facebook/신문은 적음  매출(Sales) 평균높음
# -> YouTube 중심 전략이 매우 효과적
# Cluster2 : Facebook 위주, YouTube/신문은 적음   매출(Sales) 낮음  
# -> SNS 광고 단독 전략은 효과 미흡
#  Cluster3 : 신문광고 비중이 높고 YouTube/Facebook 적음  매출액 중간 
# -> 오래된 방식의 전략, 비용 대비 효과 낮음
# marketing 데이터의 군집 분석 결과는 광고 채널 사용 패턴에 따라 
# 마케팅 캠페인을 분류하고,
# 각 그룹의 성과를 비교함으로써, 향후 더 효율적인 마케팅 
# 전략을 수립하는 근거를 제공

# 패키지 설치 (최초 1회만)
# install.packages("datarium")
# install.packages("factoextra")
# 패키지 로드
library(datarium)
library(factoextra)
# 데이터 불러오기
data("marketing")
df <- marketing
library(dplyr)
glimpse(df)
## Rows: 200
## Columns: 4
## $ youtube   <dbl> 276.12, 53.40, 20.64, 181.80, 216.96, 10.44, 69.00, 144.24, …
## $ facebook  <dbl> 45.36, 47.16, 55.08, 49.56, 12.96, 58.68, 39.36, 23.52, 2.52…
## $ newspaper <dbl> 83.04, 54.12, 83.16, 70.20, 70.08, 90.00, 28.20, 13.92, 1.20…
## $ sales     <dbl> 26.52, 12.48, 11.16, 22.20, 15.48, 8.64, 14.16, 15.84, 5.76,…
# 광고비만 선택 (Sales는 제외)
df_cluster <- df[,c("youtube", "facebook", "newspaper")]
# 정규화 (평균 0, 표준편차 1)
df_scaled <- scale(df_cluster)
set.seed(123)  # 재현 가능성 확보
km_result <- kmeans(df_scaled, centers = 3, nstart = 25)
# 군집 결과 확인
km_result$cluster  # 각 관측치의 군집 번호
##   [1] 1 1 1 1 1 1 3 3 3 2 3 2 1 3 1 1 1 1 3 2 1 2 3 2 3 2 2 2 2 3 2 3 3 2 3 2 2
##  [38] 1 3 1 2 1 2 2 3 2 3 2 2 3 2 3 1 1 2 1 3 3 1 2 3 1 2 3 1 3 3 3 2 1 1 3 3 3
##  [75] 2 1 3 3 3 3 3 2 3 1 1 1 3 1 1 1 3 3 1 1 3 1 2 2 1 1 2 1 2 2 2 1 3 3 3 2 2
## [112] 2 2 2 1 1 3 3 1 3 1 3 2 3 1 3 1 3 2 3 3 2 3 1 1 3 3 1 3 2 3 1 1 3 3 3 2 1
## [149] 3 3 2 3 2 1 2 3 1 3 1 3 2 1 2 2 3 1 3 2 1 2 3 1 3 2 2 1 2 2 2 2 2 2 3 1 2
## [186] 1 3 2 2 3 3 3 3 2 2 3 3 2 1 2
fviz_cluster(km_result, data = df_scaled,
             palette = "jco", 
             ggtheme = theme_minimal(),
             main = "K=3 광고비 기준 K-Means 군집 결과")

# 6. 원본 데이터에 군집 번호 추가
df$Cluster <- as.factor(km_result$cluster)
# 7. dplyr로 군집별 평균 광고비 + 매출 요약
df %>%
  group_by(Cluster) %>%
  summarise(across(c(youtube, facebook, newspaper, sales),
                   mean, .names = "avg_{.col}")) %>%
  arrange(Cluster)
## # A tibble: 3 × 5
##   Cluster avg_youtube avg_facebook avg_newspaper avg_sales
##   <fct>         <dbl>        <dbl>         <dbl>     <dbl>
## 1 1             198.          45.2          66.3      21.3
## 2 2             264.          22.1          22.4      18.9
## 3 3              83.4         19.1          25.3      11.5
# 실무적 해석
# Cluster 1: YouTube 광고 중심 → 매출도 가장 높음
# Cluster 2: Facebook + Newspaper 혼합 → 중간 매출
# Cluster 3: 신문 위주 전통형 광고 → 가장 낮은 매출


# 실루엣 계수
# 1. 거리 행렬 계산
dist_matrix <- dist(df_scaled)
# 2. 실루엣 객체 계산
library(cluster)
sil <- silhouette(km_result$cluster, dist_matrix)
# 3. 실루엣 시각화
library(factoextra)
fviz_silhouette(sil)
##   cluster size ave.sil.width
## 1       1   60          0.26
## 2       2   65          0.31
## 3       3   75          0.33

# 4. 평균 실루엣 계수 출력
mean(sil[, 3])  # 세 번째 열이 실루엣 계수 S
## [1] 0.3050502
# 엘보우 기법
library(factoextra)

# 엘보우 기법으로 최적 군집 수 찾기
fviz_nbclust(df_scaled, kmeans, method = "wss") +
  geom_vline(xintercept = 3, linetype = 2, color = "red") +
  labs(title = "엘보우 기법을 통한 최적 군집 수 찾기 (WSS 기준)",
       x = "군집 수 K", y = "군집 내 제곱합 (WSS)")

# 혼합분포군집
# 1. 패키지 로드 및 데이터 준비
# install.packages("mclust")
library(mclust)
## Package 'mclust' version 6.1.1
## Type 'citation("mclust")' for citing this R package in publications.
data("faithful")
glimpse(faithful)
## Rows: 272
## Columns: 2
## $ eruptions <dbl> 3.600, 1.800, 3.333, 2.283, 4.533, 2.883, 4.700, 3.600, 1.95…
## $ waiting   <dbl> 79, 54, 74, 62, 85, 55, 88, 85, 51, 85, 54, 84, 78, 47, 83, …
# eruptions
# 분출 시간 (분 단위) – 
# Old Faithful 간헐천이 한 번 분출하는 데 걸리는 시간
# waiting
# 다음 분출까지의 대기 시간 (분 단위) – 
# 분출이 끝난 뒤 다음 분출까지 기다리는 시간
# 데이터 로드
data(faithful)
# 산점도 시각화
plot(faithful,
     main = "Old Faithful 간헐천 분출 유형 시각화",
     xlab = "분출 시간 (minutes)",
     ylab = "대기 시간 (minutes)",
     pch = 19,
     col = "steelblue")

# 좌하단: 짧은 분출, 짧은 대기
# 우상단: 긴 분출, 긴 대기
# 두 개의 뚜렷한 패턴(=혼합 분포 구조)이 시각적으로 확인-> 혼합분포 군집
# 의미 간헐천 활동이 약한 경우-> 다음도 짧을 가능성 높음
# 예측 긴 분출 후 → 다음도 긴 대기 예상
# ➡ 운영·예측·관광 안내 등 실용적 응용 가능
# 2. 혼합모형 군집(Gaussian Mixture Model) 수행
model <- Mclust(faithful)
# 혼합분포군집(Mixture Model Clustering)을 실행하는 핵심 명령어
# 3. 모델 요약
summary(model)
## ---------------------------------------------------- 
## Gaussian finite mixture model fitted by EM algorithm 
## ---------------------------------------------------- 
## 
## Mclust EEE (ellipsoidal, equal volume, shape and orientation) model with 3
## components: 
## 
##  log-likelihood   n df       BIC       ICL
##       -1126.326 272 11 -2314.316 -2357.824
## 
## Clustering table:
##   1   2   3 
##  40  97 135
# 3개의 군집이 모두:
# 타원형 분포
# 같은 크기(volume), 같은 모양(shape), 같은 방향(orientation)
# → 군집이 비슷한 구조로 형성되었음을 의미
# 실용적 해석 예시 (가능한 가설)
#군집 1: 짧은 분출 + 짧은 대기 (아주 빠른 작동)
#군집 2: 중간 분출 + 대기 (중간 유형)
#군집 3: 긴 분출 + 긴 대기 (일반적인 작동 패턴)
#(→ faithful은 사실 2개 혼합구조로 알려졌지만, 3개로도 충분히 유의미한 구분 가능)
# 로그 가능도는 클수록(=덜 음수일수록) 좋습니다.
# 로그 가능도 최대 도달: EM 알고리즘이 더 이상 개선 불필요하다고 판단 → 수렴 완료
# 4. 군집 결과 시각화
plot(model, what = "classification")  # 각 관측치를 군집별 색상으로