데이터 분석/R

[R] K-means clustering (K-평균 군집화) 1

eunki 2021. 7. 8. 20:21
728x90

Clustering (군집화)

유사한 성질을 가지는 데이터 끼리 cluster(군집)를 나누는 과정

 

K-means clustering (K-평균 군집화)

K개의 중심을 정하고, 그 중심을 기반으로 clustering하는 기법

 

K-means process

1. 랜덤하게 K개의 점을 찍고 각 점을 중심으로 데이터들을 할당

2. 할당된 군집에서 다시 중심점을 찾고 해당 중심점에서 가장 가까운 데이터로 재군집화

3. 군집에 할당된 데이터들이 바뀌지 않을 때 까지 2번의 과정을 반복

 

K 개수를 선택하는 방법

1. 사전 정보(domain knowledge)를 바탕으로 설정

2. Within Sum of square(WSS) 그래프에서 Elbow point로 설정

3. Silhouette method : 군집 내 거리(a)와 최근접 군집 간의 거리(b)를 비교하여 a는 최소, b는 최대가 되는 k로 설정

 

 

 


데이터 불러오기

df <- read.csv('Wholesale customers data.csv', stringsAsFactors = F, header = T)

 



데이터 확인

head(df)

 



범주형 데이터 펙터로 변경

df$Channel <- df$Channel %>% as.factor() 
df$Region <- df$Region %>% as.factor()

 



결측치 확인

colSums(is.na(df))

 

 


변수별 기술통계 및 분포 확인

summary(df)

 

 

boxplot(df[,3:ncol(df)])

 



지수표기법 변경

options(scipen = 100) 
boxplot(df[,3:ncol(df)])

 



이상치 제거

temp <- NULL 

for (i in 3:ncol(df)) { 
  temp <- rbind(temp, df[order(df[,i], decreasing = T),] %>% slice(1:5)) 
}

temp %>% arrange(Fresh) %>% head()

 

→ 중복 데이터 존재

 

 

 

중복 제거

anti_join() : 같은 데이터들을 찾아서 제거 

temp <- distinct(temp)  # 중복 제거 
df.rm.outlier <- anti_join(df, temp)  # df에서 temp 제거

 



이상치 제거 후 박스플롯 확인
par() : 하나의 그림에 여러 개의 plot 그리기

par(mfrow = c(1,2)) 

boxplot(df[,3:ncol(df)]) 
boxplot(df.rm.outlier[,3:ncol(df.rm.outlier)])

 



k 군집 개수 설정 (Elbow method)

install.packages("factoextra") 
library(factoextra)

set.seed(1234) 

fviz_nbclust(df.rm.outlier[,3:ncol(df.rm.outlier)], kmeans, method = "wss", k.max = 15) + 
  theme_minimal() + 
  ggtitle("Elbow Method")

 

→ k = 5

 


k 군집 개수 설정 (Silhouette method)

fviz_nbclust(df.rm.outlier[,3:ncol(df.rm.outlier)], kmeans, method = "silhouette", k.max = 15) + 
  theme_minimal() + 
  ggtitle("Silhouette Method")

 

→ k = 3

 



k means 모델 생성

df.kmeans <- kmeans(df.rm.outlier[,3:ncol(df.rm.outlier)], centers = 5, iter.max = 1000) 
df.kmeans

 



군집별 평균치 시각화

fill : 범례 색상 
cex : 범례 크기 

barplot(t(df.kmeans$centers), beside = TRUE, col = 1:6)
legend("topleft", colnames(df[,3:8]), fill = 1:6, cex = 0.5)

 



5. raw data에 cluster 할당

df.rm.outlier$cluster <- df.kmeans$cluster 
head(df.rm.outlier)

728x90