Post List

2019년 8월 11일 일요일

ggplot2 패키지를 더 효율적으로! ggplot의 확장 패키지를 이용한 시각화



ggplot2 패키지는 시각화를 대표하는 패키지로써, R의 가장 큰 자랑이기도 합니다. 그러나 기본 패키지 만으로는 모든 데이터를 표현하기 힘들기에, 이를 보완하기 위한 각종 확장 패키지들이 존재합니다. 이러한 확장 패키지를 잘 사용한다면 더욱 다채로운 시각화 표현이 가능합니다.


library(stringr)
library(dplyr)

KOR_ticker = 
  read.csv('https://raw.githubusercontent.com/hyunyulhenry/quant_cookbook/master/data/KOR_ticker.csv',
           row.names = 1,
           stringsAsFactors = FALSE)
KOR_sector = 
  read.csv('https://raw.githubusercontent.com/hyunyulhenry/quant_cookbook/master/data/KOR_sector.csv',
           row.names = 1,
           stringsAsFactors = FALSE)
  
KOR_ticker$'종목코드' =
  str_pad(KOR_ticker$'종목코드', 6,'left', 0)
KOR_sector$'CMP_CD' =
  str_pad(KOR_sector$'CMP_CD', 6, 'left', 0)

data_market = left_join(KOR_ticker, KOR_sector,
                         by = c('종목코드' = 'CMP_CD',
                                '종목명' = 'CMP_KOR'))

data_market = data_market %>%
  rename(`시가총액` = `시가총액.원.`)

data_market = data_market %>%
  mutate(`PBR` = as.numeric(PBR),
         `PER` = as.numeric(PER),
         `ROE` = PBR / PER,
         `ROE` = round(ROE, 4),
         `size` = ifelse(`시가총액` >=
                           median(`시가총액`, na.rm = TRUE),
                                        'big', 'small')
  )


먼저 필요한 데이터를 불러온 후 클렌징 하도록 하겠습니다.
퀀트 투자 쿡북의 책 내용을 그대로 따오도록 합니다.
https://hyunyulhenry.github.io/quant_cookbook/section-38.html#section-39


8월말에 종이책으로 발간됩니다.
한권씩 매수매수..... 플리즈...


1. corrplot


corrplot은 상관관계 행렬을 시각화해주는 확장 패키지로써, 상관관계의 강도를 더욱 이해하기 쉽게 만들어 줍니다.


data_market %>%
  select(PER, PBR, ROE) %>%
  mutate(PER = min_rank(PER),
        PBR = min_rank(PBR),
        ROE = min_rank(desc(ROE))) %>%
  cor(use = 'complete.obs')

          PER        PBR        ROE
PER 1.0000000  0.4617038  0.6097884
PBR 0.4617038  1.0000000 -0.3525682
ROE 0.6097884 -0.3525682  1.0000000


종목의 PER, PBR, ROE의 랭크를 구한 후 (ROE의 경우 내림차순) 상관관계를 구해주었습니다. 단순히 숫자로 표현되어 한눈에 확인하기 힘듭니다.


library(corrplot)

data_market %>%
  select(PER, PBR, ROE) %>%
  mutate(PER = min_rank(PER),
        PBR = min_rank(PBR),
        ROE = min_rank(desc(ROE))) %>%
  cor(use = 'complete.obs') %>%
  corrplot(method = 'circle',
           addCoef.col = 'white', number.cex = 0.7)



상관관계의 부호가 색깔, 크기가 원의 지름으로 표현되어 훨씬 이해하기 쉽습니다.
method를 통해 그림 모양을 변경할 수도 있으며, 각종 인자를 변경해가며 원하는 그림을 나타낼 수 있습니다. 자세한 사용법은 아래 링크를 참조하시기 바랍니다.

https://cran.r-project.org/web/packages/corrplot/vignettes/corrplot-intro.html


2. waffle

waffle 패키지는 와플 차트를 그려줌으로써, 각 데이터의 비율을 이해하기 쉽게 합니다.


library(waffle)
library(dplyr)
library(magrittr)

df = data_market %>%
  select(SEC_NM_KOR) %>%
  filter(!is.na(SEC_NM_KOR)) %>%
  table() %>% sort(decreasing = TRUE)

df
.
                IT     경기관련소비재             산업재           건강관리               소재 
               574                393                332                226                216 
        필수소비재               금융             에너지           유틸리티 커뮤니케이션서비스 
                96                 78                 23                 19                  7 


먼저 table() 함수를 이용해 각 섹터별 구성종목수를 확인해보도록 합니다.

df %>% 
  divide_by(5) %>%
  waffle(color = rainbow(10),
       size = 1, legend_pos = "bottom")



스케일링을 위해 divide_by()를 통해 5로 나눠준 다음, waffle()을 통해 와플차트를 표현합니다. 각 섹터의 갯수만큼 정사각형으로 표현되어 비율의 차이를 한눈에 확인할 수 있습니다.

https://github.com/hrbrmstr/waffle/tree/cran


3. treemapify


주식을 하시는 분이라면 이런 그림을 많이 보셨을 겁니다. treemap을 통해 시가총액을 사각형으로 표현하였으며, 그 내부에 각 종목명 및 수익률이 표현되어 있습니다.

R의 treemapify 패키지를 사용한다면 treemap을 매우 쉽게 그릴 수 있습니다.


data_market %>%
  select(시가총액, SEC_NM_KOR, PBR) %>%
  filter(!is.na(SEC_NM_KOR)) %>%
  mutate(시총비 = 시가총액 / sum(시가총액),
            시총비 = round(시총비, 3)) %>%
  group_by(SEC_NM_KOR) %>%
  summarize(시총비 = sum(시총비),
               PBR = median(PBR, na.rm = TRUE)) %>%
  ggplot(aes(area = 시총비,
             fill = SEC_NM_KOR,
             label = paste(SEC_NM_KOR, PBR, sep = '\n\n'))) +
  geom_treemap() +
  geom_treemap_text(place = 'centre') +
  theme(legend.position = "none")




먼저 mutate를 통해 시총비를 구해준 후, 섹터 별 시총비와 PBR의 median 값을 구해줍니다.

그 후 ggplot을 통해 area(영역)은 시총비, fill(영역색)은 색터 이름, 라벨은 paste 함수를 통해 섹터명과 PBR을 합쳐주며, \n을 통해 줄바꿈을 해줍니다. 그 후 treemapify 패키지의 geom_treemap() 함수를 이용해주면 treemap이 표현됩니다.

각 사각형의 크기는 시총비를 나타내며, IT와 경기관련소비재가 국내 시총의 절반 정도를 차지함이 보입니다. 반면 건강관리는 시총비중이 그렇게 크지 않음에도 불구하고 PBR이 2.59로 매우 높음이 보입니다.

https://wilkox.org/treemapify/



4. ggrepel

ggplot을 이용해 그림 위에 텍스트를 표현할 경우 잘 보이지 않을 때가 있습니다. ggrepel은 이러한 텍스트를 보기 쉽게 표현해주는 확장 패키지입니다.


library(ggrepel)
library(gridExtra)

p1 = data_market %>%
  filter(!is.na(SEC_NM_KOR)) %>%
  group_by(SEC_NM_KOR) %>%
  summarize(ROE_sector = median(ROE, na.rm = TRUE),
            PBR_sector = median(PBR, na.rm = TRUE)) %>%
  ggplot(aes(x = ROE_sector, y = PBR_sector,
             color = SEC_NM_KOR, label = SEC_NM_KOR)) +
  geom_point() +
  geom_text(color = 'black', size = 3, vjust = 1.3) +
  theme(legend.position = "none")

p1


각 섹터의 ROE와 PBR의 median값을 점으로 나타낸 후, geom_text() 함수를 통해 텍스트를 표현했습니다. 그러나 산업재, 필수소비재, 에너지, 경기관련소비재의 경우 글씨들이 몰려있어 구분하기가 쉽지 않습니다.


p2 = data_market %>%
  filter(!is.na(SEC_NM_KOR)) %>%
  group_by(SEC_NM_KOR) %>%
  summarize(ROE_sector = median(ROE, na.rm = TRUE),
            PBR_sector = median(PBR, na.rm = TRUE)) %>%
  ggplot(aes(x = ROE_sector, y = PBR_sector)) +
  geom_point() +
  geom_label_repel(
    aes(x = ROE_sector, y = PBR_sector,
        label = SEC_NM_KOR, color = SEC_NM_KOR)
    ) +
  theme(legend.position = "none")

p2



동일한 내용이지만 ggrepel 패키지의 geom_label_repel() 함수를 이용할 경우 훨씬 구분하기가 쉽게 표현됩니다.

grid.arrange(p1, p2, ncol = 1)


gridExtra 패키지의 grid.arrange() 함수는 여러개의 ggplot 그림을 하나의 화면에 출력해줍니다. ggrepel  패키지를 이용하는 것이 내용을 확인하기 훨씬 쉽습니다.

https://cran.r-project.org/web/packages/ggrepel/vignettes/ggrepel.html


5. ggradar




레이더 혹은 스파이더 차트는 게임에 많이 나오는 차트입니다. 흔히 능력치를 보기쉽게 나타내주는 그래프입니다.

ggradar 패키지의 경우 CRAN의 공식 패키지가 아니므로 github를 통해 다운로드 받아야 됩니다.


devtools::install_github("ricardo-bion/ggradar", 
                          dependencies = TRUE)

library(ggradar)
library(scale)
library(dplyr)
data_market %>% filter(!is.na(SEC_NM_KOR)) %>% mutate(tile_size = ntile(desc(시가총액), 5)) %>% group_by(tile_size) %>% summarize(ROE = median(ROE, na.rm = TRUE), PBR = median(PBR, na.rm = TRUE), PER = median(PER, na.rm = TRUE), DY = median(배당수익률, na.rm = TRUE)) %>% mutate_at(vars(-tile_size), rescale) %>% ggradar() + theme(legend.position = 'bottom', legend.title = element_blank())



먼저 ntile() 함수를 이용해 시가총액을 5개 분위 (내림차순)으로 나눠주도록 합니다. 그 후 각 그룹별 ROE, PBR, PER, DY를 구해준 후, 분위수명(tile_size)를 제외한 컬럼을 scale 패키지의 rescale() 함수를 이용해 0에서 1 값이 되도록 표준화 해줍니다.

그 후 ggradar() 함수를 입려해주면 레이더 차트가 자동으로 생성됩니다.

분위수가 높을 수록, 즉 시가총액이 클수록 ROE와 PBR은 높은 Quality 주식이 많고, 분위수가 낮을수록, 즉 시가총액이 작을수록 ROE와 PBR이 낮은 Junk 주식이 많음이 보입니다.


이 외에도 ggplot의 다양한 확장 패키지는 아래의 사이트에서 확인할 수 있습니다.

http://www.ggplot2-exts.org/gallery/

댓글 없음:

댓글 쓰기