시계열 군집

안성인·2022년 2월 15일
1

📖 시계열 데이터를 계층적, 분할적 군집화하기 위한 방법을 간단하게 코드 위주로 각각 알아봅시다.


<군집화 가능한 시계열 데이터의 형태로 변환>

  • 기존 데이터는 각 컬럼이 각 집단의 시계열 정보를 가지고 있습니다. 이를 전치시켜 각 로우데이터가 각 집단 별 시계열 데이터가 되도록 군집화할 수 있게 데이터를 변형하겠습니다.

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 ...

<계층적 군집화>


군집 및 시각화(1)

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기반 클러스터링

DTW가 궁금하다면 클릭!!


군집 및 시각화(2)

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 

<분할적 군집화>


군집 및 평가 지표 도출

  • PAM 군집을 이용해 여러 개의 군집화를 진행한 뒤, 평가 지표를 확인하여 최적의 군집 개수를 도출해보도록 하겠습니다.
#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')

1번째 군집의 개수로 군집화를 할 경우, 실루엣 지표가 가장 높다는 것이 확인 가능합니다. 즉 2개의 군집부터 알아보았기 때문에, 1번째 군집의 개수는 2개인 것을 알 수 있습니다.

최적의 군집 시각화

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) 
시계열 클러스터의 Centroids가 의미하는 바는 “각 클러스터의 대표 분포 개체”이고 해당 분포와 “비슷한 분포”를 가진 개체끼리 분류 한다고 볼 수 있습니다.


각 시계열 객체의 군집 결과 확인

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
profile
함께 공부해요!

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

안녕하세요:) 시계열군집분석에 고민이 많았는데 명령어와 명확할 설명 감사합니다!.. 혹시 시계열군집분석을 시행할 때 여러집단의 값을 시계열군집을 돌릴 수 있을까요?(변수 3개를 동시에 시계열군집분석을 돌리고자 합니다)

답글 달기