📖 시계열 데이터를 계층적, 분할적 군집화하기 위한 방법을 간단하게 코드 위주로 각각 알아봅시다.
library(tidyr)
library(tidyverse)
da_visnights<- as.data.frame(visnights)
tail(visnights)
## 시계열 데이터의 년도/분기는 rowname이 아니기에 따로 추출하지 못하여 새로 생성
da_visnights2 <- data.frame(year = rep(c(1998:2016),each = 4),season = rep(c('Q1','Q2','Q3','Q4'), 19),da_visnights)
da_visnights2 <- da_visnights2%>% unite('year',year,season)
da_visnights2$year <- gsub('_',' ', da_visnights2$year)
## 컬럼을 로우네임으로 변환하고 전치
cl_da_visnights <- da_visnights2 %>% column_to_rownames('year') %>% t()
head(cl_da_visnights)
> head(cl_da_visnights)
1998_Q1 1998_Q2 1998_Q3 1998_Q4 1999_Q1 1999_Q2
NSWMetro 9.047095 6.962126 6.871963 7.147293 7.956923 6.542243
NSWNthCo 8.565678 7.124468 4.716893 6.269299 9.493901 5.401201
NSWSthCo 5.818029 2.466437 1.928053 2.797556 4.853681 2.759843
NSWSthIn 2.679538 3.010732 3.328869 2.417772 3.224285 2.428489
NSWNthIn 2.977507 3.477703 3.014770 3.757972 3.790760 3.395284
QLDMetro 12.106052 7.786687 11.380024 9.311460 12.671942 9.582965
1999_Q3 1999_Q4 2000_Q1 2000_Q2 2000_Q3 2000_Q4 ...
NSWMetro 6.330364 7.509212 7.662491 6.341802 7.827301 9.579562 ...
NSWNthCo 5.542626 6.383474 8.337008 4.923476 5.134491 6.389888 ...
NSWSthCo 2.041827 2.650677 5.367951 3.460795 1.606173 2.563254 ...
NSWSthIn 2.893273 2.814578 2.553072 2.368211 2.934893 2.561272 ...
NSWNthIn 3.626120 3.691498 3.135834 2.824604 3.390675 2.946215 ...
QLDMetro 11.192969 9.871108 11.709851 9.357777 11.363533 9.923923 ...
library(TSdist)
library(dplyr)
par(mfrow = c(1,2))
cl_da_visnights %>% TSdist::TSDatabaseDistances(distance = 'dtw') %>% hclust(method = 'average') %>% plot(main = 'DTW Cluster')
# DTW기반 클러스터링
cl_da_visnights %>% TSdist::TSDatabaseDistances(distance = 'acf') %>% hclust(method = 'average') %>% plot(main = 'ACF Cluster')
# ACF기반 클러스터링
h_tscluster <- cl_da_visnights %>% TSdist::TSDatabaseDistances(distance = 'acf') %>% hclust(method = 'average')
library(factoextra)
fviz_dend(h_tscluster, k = 4, # k = 군집 개수
cex = 0.6, # label size,
lwd = 1.2,
palette = 'jco',
color_labels_by_k = T, # 라벨 칼라 변경 유무
rect = TRUE,
rect_border = 'jco',
rect_fill = T,
repel = T) +
# repel = T : text가 겹치는 것을 방지
labs(title = 'time series Dendrogram')
## 4개의 군집으로 정했을 때의 군집화 결과 확인
group <- cutree(h_tscluster, k = 4)
group
table(group)
> group
NSWMetro NSWNthCo NSWSthCo NSWSthIn NSWNthIn QLDMetro QLDCntrl QLDNthCo
1 2 2 3 4 3 1 2
SAUMetro SAUCoast SAUInner VICMetro VICWstCo VICEstCo VICInner WAUMetro
1 2 4 1 2 2 1 1
WAUCoast WAUInner OTHMetro OTHNoMet
4 4 3 3
> table(group)
group
1 2 3 4
6 6 4 4
#install.packages('htmltools')
## dtwclust패키지의 tsclust함수가 실행되지 않을 시 htmltools를 다시 다운받아주세요.
pam_tscluster <- dtwclust::tsclust(cl_da_visnights, type = 'partitional', k = 2L:15L, distance = 'dtw', centroid = 'pam')
# centroid 파라미터로 means, median 등으로 군집 방법 변경 가능
## 최적의 군집 개수를 알아내기 위해 2개부터 15개의 군집으로 모두 실행
eval_clust <- sapply(pam_tscluster, cvi) # 7개의 평가 지표
eval_clust
> eval_clust
[,1] [,2] [,3] [,4] [,5]
Sil 0.60222571 0.53261760 0.40050363 0.39035876 0.21873631
SF 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
CH 31.29120799 21.50480020 11.94027659 17.11881856 8.51057997
DB 0.33343841 0.48950171 1.29691812 0.58496800 1.31562045
DBstar 0.33343841 0.70097518 1.61296159 0.65128953 2.60938206
D 0.07871654 0.11732471 0.13592293 0.27769208 0.12816925
COP 0.17662094 0.08465367 0.07653567 0.05077837 0.06231594
[,6] [,7] [,8] [,9] [,10] [,11]
Sil 0.27166857 0.25677139 0.19617030 0.09831236 0.17664372 0.07162558
SF 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000 0.00000000
CH 11.42549460 5.48324494 5.17722931 5.01361344 8.06434069 6.67073816
DB 0.67369345 0.63502724 0.72579894 0.96304155 0.50570706 0.54387511
DBstar 0.85782061 2.00066196 2.30664715 2.36052015 0.72086120 0.95746395
D 0.36580863 0.12316141 0.12316141 0.12816925 0.38127489 0.41515842
COP 0.04095813 0.05574566 0.04627624 0.03692245 0.01917745 0.02279216
[,12] [,13] [,14]
Sil 0.11817856 0.117987294 0.04228954
SF 0.00000000 0.000000000 0.00000000
CH 6.79096846 7.694340066 4.23434696
DB 0.46690076 0.368074971 0.50458991
DBstar 0.84898248 0.523479526 1.50472759
D 0.39751315 0.747529184 0.20793851
COP 0.01504372 0.009212244 0.01560066
plot(eval_clust[1,], type = 'l' ,xlab = 'The number of clusters',
ylab = '극댓값 부분을 찾아주세요', main = 'sil index')
opt_pam_tscluster <- dtwclust::tsclust(cl_da_visnights, type = 'partitional', k = 2L, distance = 'dtw', centroid = 'pam')
# 각 군집의 series, centroid 관찰
plot(opt_pam_tscluster, type = 'sc') # series and centroid
## centroid는 점선으로 나타남.
# 첫 번째 군집의 series 관찰
plot(opt_pam_tscluster, type = 'series', clus = 1L)
# 첫 번째 군집의 centroid 관찰
plot(opt_pam_tscluster, type = 'centroid', clus = 1L)
t(cbind(cl_da_visnights[,0], cluster = opt_pam_tscluster@cluster))
> t(cbind(cl_da_visnights[,0], cluster = opt_pam_tscluster@cluster))
NSWMetro NSWNthCo NSWSthCo NSWSthIn NSWNthIn QLDMetro QLDCntrl
cluster 2 2 1 1 1 2 1
QLDNthCo SAUMetro SAUCoast SAUInner VICMetro VICWstCo VICEstCo
cluster 1 1 1 1 2 1 1
VICInner WAUMetro WAUCoast WAUInner OTHMetro OTHNoMet
cluster 1 1 1 1 1 1
안녕하세요:) 시계열군집분석에 고민이 많았는데 명령어와 명확할 설명 감사합니다!.. 혹시 시계열군집분석을 시행할 때 여러집단의 값을 시계열군집을 돌릴 수 있을까요?(변수 3개를 동시에 시계열군집분석을 돌리고자 합니다)