아이티월 수업일지(R)

22-08-30 chap18_ClusteringAnalysis

서부남93 2022. 8. 31. 12:39

chap18_ClusteringAnalysis

 

###################################################
# 군집분석(Clustering)
###################################################
# 유사성 거리에 의한 유사객체를 묶어준다.
# 거리를 측정하여 집단의 이질성과 동질성을 평가하고, 이를 통해서 
# 군집을 형성한다..
# 유사성 거리 : 유클리드 거리
# y변수가 없는 데이터 마이닝 기법
# 예) 그룹화를 통한 예측(그룹 특성 차이 분석-고객집단 이해)
# 주요 알고리즘 : hierarchical, k-means


# 1. 유클리드 거리
# 유클리드 거리(Euclidean distance)는 두 점 사이의 거리를 계산하는 
# 방법으로 이 거리를 이용하여 유클리드 공간을 정의한다.

# (1) matrix 생성
x <- matrix(1:9, nrow=3, by=T) 
x

# (2) matrix 대상 유클리드 거리 생성 함수
# 형식) dist(x, method="euclidean") -> x : numeric matrix, data frame
distance <- dist(x, method="euclidean") # method 생략가능
distance 

# p1과 p2 거리식 
sqrt(sum((x[1,] - x[2,])^2)) # 5.196152

# p1과 p3 거리식 
sqrt(sum((x[1,] - x[3,])^2)) # 10.3923

# 3) 활용분야 
# 1. 분류분석 : kNN
# 2. 군집분석 : 계층적, 비계층적 
# 3. 추천모델 : 유사도 계산 


# 2. 계층적 군집분석(탐색적 분석)
# - 계층적 군집분석(Hierarchical Clustering)
# - 거리가 가장 가까운 대상부터 결합하여 나무모양의 
#   계층구조를 상향식(Bottom-up)으로 만들어가면서 군집을 형성 

# 1) 군집분석(Clustering)분석을 위한 패키지 설치
install.packages("cluster") # hclust() : 계층적 클러스터 함수 제공
library(cluster) # 일반적으로 3~10개 그룹핑이 적정


# 2) 데이터 생성(5개 포인트)  
p1 = c(1,1)
p2 = c(2,1)
p3 = c(2,4)
p4 = c(4,3)
p5 = c(5,4)

df = data.frame(p1,p2,p3,p4,p5)
mt = t(df) # 전치행렬 
mt


# 3) 거리계산=유클리드 공간  
dis <- dist(mt, method="euclidean") 
dis


# 4) 계층적 군집분석 : 최단연결법(단순결합기준) 
hc <-  hclust(dis, method="single")  # method = "complete"(생략 시 기본)
# method = "ward.D", "ward.D2", "single", "complete", "average" 등 

# 군집화 방법(Cluster method) 
# method = "complete" : 완전결합기준(최대거리 이용) 
# method = "single" : 단순결합기준(최소거리 이용) 
# method = "average" : 평균결합기준(평균거리 이용) 


# 5) 덴드로그램 
plot(hc, hang=-1) # hang=-1 : y=0 기준 밑선 정렬 


# 6) 군집분석 속성  
names(hc) # "height"  "method" "dist.method"   
hc$height # # 1.000000 1.414214 2.236068 2.828427
hc$method #   군집화 방법 
hc$dist.method # 거리계산식 


# 계층적 군집분석 : 평균연결법 
hc <-  hclust(dis, method="average")

plot(hc, hang=-1)

hc$height # 1.000000 1.414214 2.618034 3.639816

# {p3, (p4, p5)} = (p3,p4) + (p3,p5) / 2
(2.236068 + 3.0) / 2 # 2.618034


#---------------------------------------------
#<실습> 중1학년 신체검사 결과 군집분석
#---------------------------------------------
# 단계1 : 데이터셋 가져오기 
body <- read.csv("c:/ITWILL/3_Rwork/data/bodycheck.csv")
names(body)
str(body)


# 단계2 : 거리계산 
idist <- dist(body)
idist

# 단계3 : 계층적 군집분석 
hc <- hclust(idist) # method = "complete" : 최장연결법 

plot(hc, hang=-1) # 음수값 제외

# 3개 그룹 선정, 선 색 지정
rect.hclust(hc, k=3, border="red") # 3개 그룹 선정, 선 색 지정

# 단계4 : 각 그룹별 서브셋 만들기
cluters <- cutree(hc, k=3) # 군집 자르기
cluters # 1 2 3 1 3 3 2 1 2 1 3 2 2 3 1

#g1<- body[c(10,4,8,1,15), ]
#g2<- body[c(11,3,5,6,14), ]
#g3<- body[c(2,9,13,7,12), ]

body$cluters <- cluters

g1 <- subset(body, cluters==1)
g2 <- subset(body, cluters==2)
g3 <- subset(body, cluters==3)

# 단계5 : 군집별 특성분석 
summary(g1)
# Mean   :25.6   Mean   :149.8   Mean   :36.6 안경유무 : 1

summary(g2)
# Mean   :40.6   Mean   :158.8   Mean   :56.8  안경유무 : 2

summary(g3)
# Mean   :33.8   Mean   :161.2   Mean   :48.8 안경유무 : 1 or 2


plot(body$'체중', body$'신장', col=body$cluters)


# 3. 계층형 군집분석과 군집 자르기 

# 1) 유클리드 거리 계산 
dist_re <- dist(iris[1:4]) # dist(iris[, -5])

# 2) 계층형 군집분석(클러스터링)
hc <- hclust(dist_re)
plot(hc, hang=-1)
rect.hclust(hc, k=3, border="red") # 3개 그룹수 

# 3) 그룹수 만들기 : cutree()함수 -> 각 군집별로 군집 자르기
# 형식) cutree(계층형군집결과, k=군집수) 
ghc<- cutree(hc, k=3) # stats 패키지 제공
ghc  # 1 ~ 3 

# 칼럼 클러스터 정보 추가 
iris$cluster <- ghc

head(iris)
iris[100:120,]
tail(iris)

table(iris$cluster)
# 1  2  3 
#50 72 28


plot(iris$Sepal.Length, iris$Petal.Length, col=iris$cluster)



# 4. 비계층적 군집분석(확인적 분석)
# - 군집 수를 알고 있는 경우 이용하는 군집분석 방법

# 군집분석 종류 : 계층적 군집분석(탐색적), 비계층적 군집분석(확인적) 

# 1) data set 준비 
library(ggplot2)
data(diamonds)

nrow(diamonds) # [1] 53940
t <- sample(nrow(diamonds),1000) # 1000개 셈플링 

test <- diamonds[t, ] # 1000개 표본 추출
dim(test) # [1] 1000 10

# 데이터프레임 변환 
test_df <- as.data.frame(test)

head(test_df) # 검정 데이터
mydia <- test_df[c("price","carat", "depth", "table")] # 4개 칼럼만 선정
head(mydia)

# 2) 비계층적 군집분석(확인적 분석) - kmeans()함수 이용
# - 확인적 군집분석 : 군집의 수를 알고 있는 경우
model <- kmeans(mydia, 3)
model 
# K-means clustering with 3 clusters of sizes 302, 95, 603 - 군집수 
# Cluster means: 클러스터별 변수의 평균 
# Clustering vector: 1~3 클러스터 번호 
# Within cluster sum of squares by cluster: 각 군집내 응집도 
# Available components: 군집분석 결과의 구성요소(9개)

names(model) # 속성 확인 


# 모델 정보 
model$cluster # 분류된 클러스터 정보 
model$centers # 각 군집의 중앙값 
model$size # 각 군집의 크기 

# 모델 평가 척도 
model$totss # 제곱합의 총합 = 분리도 + 응집도 
model$withinss # 응집도 
model$tot.withinss # 응집도 총합 
model$betweenss # 분리도 

# 모델 평가 방법 
#(between_SS / total_SS =  87.4 %)

between_SS <- model$betweenss
total_SS <- model$totss # model$tot.withinss + model$betweenss
between_SS / total_SS # 0.8741169


# 3) 원형데이터에 군집수 추가
mydia$cluster <- model$cluster
head(mydia) # cluster 칼럼 확인 

# 4) 변수 간의 상관성 보기 
plot(mydia[,-5])
cor(mydia[,-5], method="pearson") # 상관계수 보기 

#install.packages('corrgram')
library(corrgram) # 상관성 시각화 
corrgram(mydia[,-5], upper.panel=panel.conf) # 수치(상관계수) 추가(위쪽)


# 5) 비계층적 군집시각화
plot(mydia$carat, mydia$price, col=mydia$cluster)
# mydia$cluster 변수로 색상 지정(1,2,3)

# 각 그룹의 중심점에 포인트 추가 
points(model$centers[,c("carat", "price")], col=c(3,1,2), pch=8, cex=5)
# col : color, pch : 중심점 문자, cex : 중심점 문자 크기
# pch(plotting character), cex(character expansion)


# 6) k-means model 시각화 
install.packages('factoextra')
library(factoextra)

fviz_cluster(model, data = mydia) # k-means 시각화 
# 4개 차원 -> 2개 차원 : 차원 축소(Dim1, Dim2)   
# Dim1(49.5%) : 첫번째 차원의 공헌도(50%) -> 제1주성분  
# Dim2(26.4%) : 두번째 차원의 공헌도(26%) -> 제2주성분 

model$centers


##############################
## 5. 군집수 찾기 
##############################

data("iris")

# data.frame -> matrix
iris_max <- as.matrix(iris[-5])
dim(iris_max) # 150   4

install.packages('NbClust') # 군집수 
library(NbClust)

nc <- NbClust(data = iris_max, distance = "euclidean", min.nc = 2, max.nc = 15, 
              method = 'complete', index = "all", alphaBeale = 0.1)


# 각 클러스터 빈도수 
table(nc$Best.nc[1,])
#0  1  2  3  4  6 15  -> 클러스터 
#2  1  2 13  5  1  2  -> 빈도수 

names(nc)

table(nc$Best.partition)
# 1  2  3 
#50 72 28