본문 바로가기
  • plotly로 바로쓰는 동적시각화 in R & 파이썬
실전에서 바로 쓰는 시계열 데이터 처리와 분석 in R/못다한 이야기

이중 Y축 그리기 in R

by 아참형인간 2021. 6. 8.
dual_axis.utf8

ggplot에서는 특별한 설정을 하지 않아도 자동적으로 X축과 Y축의 눈금과 범위를 자동적으로 설정해준다. 하지만 다음 플롯과 같이 다변량(Multi-variated) 플롯을 그릴때 맞닥치는 가장 흔한 문제는 한쪽 값이 너무 크거나 작으면 플롯이 효과적이지 않다는 것이다.

예제를 실행하기 위서는 먼저 샘플 데이터를 로딩해야 한다. 이 예제에서는 우리나라 전체 월별 전체 취업자수와 교육분야 취업자수를 사용할 것이다. 데이터 원본은 공지사항을 참조하면 다운로드 받을 수 있고 다음의 코드를 실행함으로서 데이터를 업로드 시킬 수 있다.

employees <- read.csv('./산업별_취업자_20210206234505.csv', header = TRUE, na = '-', strip.white = TRUE, stringsAsFactors = TRUE)

colnames(employees) <- c('time', 'total', 'employees.edu')

employees$time <- as.Date(paste0(employees$time, '. 01'), format = '%Y. %m. %d')

업로드한 데이터를 다음과 같이 그려본다.

library(ggplot2)
ggplot(employees, aes(x = time)) + 
  geom_line(aes(y = total, color = '전체 취업자')) + 
  geom_line(aes(y = employees.edu, color = '교육분야 취업자'))

이럴때는 플롯 우측에 두번째 Y축을 설정하고 다음과 같이 플롯을 그려주는게 효과적이다.

이와 같이 이중축 플롯은 두 변량의 비율 맞추기와 두번째 Y축 생성의 두가지 단계를 거쳐 생성할 수 있다. 여기서 하나 알아야 하는 것은 앞서 언급한 바와 같이 두번째 축은 ggplot가 자동적으로 설정하는 것이 아니라는 점이다.

1. 두 변량의 비율 맞추기

먼저 두 변량이 하나의 플롯에 적절하게 표현되기 위해서는 두 변량의 비율이 적절하게 맞아야 한다는 것이다. 이를 위해는 먼저 두 개의 변량에 대한 최대값 혹은 최소값의 비율을 사용하여 한 쪽 변량의 데이터 값을 전체적으로 변환해서 플롯을 그려야 한다는 점이다.

먼저 두 변량의 비율을 구해보자.

앞선 예에서와 같이 전체 취업자의 최대값과 교육분야 취업자의 최대값의 비율은 다음과 같이 구할 수 있다.

max_ratio <- max(employees$total)/max(employees$employees.edu)
max_ratio
## [1] 14.10302

위에서 보이듯이 (전체 취업자 최대값 / 교육분야 취업자 최대값)은 14.1로 산출되는데 전체 취업자수는 교육분야 취업자수의 약 14배 정도 비율이 된다는 것이다. 따라서 교육분야 취업자수에 14.1을 곱한 데이터를 그리면 두 변량의 표현이 가능한 플롯이 그려진다.

첫번째 geom_line()의 Y축 설정은 전체 취업자 수를 Y축에 설정하였기 때문에 전체 Y축의 설정은 전체 취업자수인 total 열의 값으로 설정된다. 두번째 geom_line()의 Y축 설정은 교육분야 취업자 수를 설정하되 전체 취업자 수와 비율을 맞추기 위해 앞서 구했던 max_ratio를 곱한 값을 설정하였다.

ggplot(employees, aes(x = time)) + 
  geom_line(aes(y = total, color = '전체 취업자')) + 
  geom_line(aes(y = max_ratio * employees.edu, color = '교육분야 취업자'))

2. 변형된 변량값을 측정하기 위한 두 번째 Y축 설정

위의 플롯에서 보듯이 이제 대략 두 변량이 한 플롯에 효과적으로 표현된다. 하지만 이 플롯 상에서는 데이터는 교육분야 취업자수의 수치를 측정할 축이 없기 때문에 데이터 값을 측정할 수 없다. 따라서 교육분야 취업자 데이터를 측정할 두 번째 Y축을 설정해 주어야 한다.

두 번째 Y축은 scale_y_continuous()sec.axis 매개변수를 통해 설정할 수 있는데 이 매개변수는 다시 sec_axis()를 사용하여 설정할 수 있다.

sec_axis()에 사용되는 매개변수는 여러개가 있는데 일단 이 예제에서는 transname매개변수만을 사용한다.

trans는 설정된 Y축의 값을 어떻게 변환할 지에 대한 함수식을 전달하는 매개변수이다. 여기서 중요하게 사용되는 키워드는 ~.인데 Y축의 값을 표현한다고 생각하면 쉽다.

아래의 예는 ~.을 사용하는 예를 보여준다.

### 실습용 데이터프레임을 생성한다. x열과 y열을 가지는 데이터 프레임으로 각각 1부터 10까지의 값을 가진다. 
dummy <- data.frame(x = 1:10, y = 1:10)

### 두번째 Y축은 첫번째 Y축에 5을 더한 값으로 설정
ggplot(dummy , aes(x = x, y = y)) + 
  scale_y_continuous(
  sec.axis = sec_axis(~.+5, name="+5")
  )

### 두번째 Y축은 첫번째 Y축에 5을 곱한 값으로 설정
ggplot(dummy , aes(x = x, y = y)) + 
  scale_y_continuous(
    sec.axis = sec_axis(~.*5, name="*5")
  )

### 두번째 Y축은 첫번째 Y축에 2제곱 값으로 설정
ggplot(dummy , aes(x = x, y = y)) + 
  scale_y_continuous(
    sec.axis = sec_axis(~.^2, name="^2")
  )

따라서 현재 설정된 Y축 값에 적용할 수식을 뒤에 붙여주는데 위의 예에서는 max_ratio의 비율만큼 나누어 주면 된다. 따라서 trans = ~./max_ratio와 같이 실행하면 적절히 설정된다. name은 축 제목으로 사용될 문구를 설정한다.

ggplot(employees, aes(x = time)) + 
  geom_line(aes(y = total, color = '전체 취업자')) + 
  geom_line(aes(y = max_ratio * employees.edu, color = '교육분야 취업자')) +
  scale_y_continuous(name = "전체 취업자",  ## 첫번째 Y축 이름 설정
    sec.axis = sec_axis(trans=~ ./max_ratio, name="교육분야 취업자")) ## 두번째 Y축 변환식과 이름 설정

하나 주의깊게 봐야할 점은 두 번째 geom_line()의 Y축 설정은 max_ratio를 곱했지만 두 번째 Y축의 변환식에서는 max_ratio를 나누었다는 점이다.

이 플롯을 보다 보기 좋게 만들기 위해 플롯의 범례 순서와 위치를 재설정하였다.

ggplot(employees, aes(x = time)) + 
  geom_line(aes(y = total, color = '전체 취업자')) + 
  geom_line(aes(y = max_ratio * employees.edu, color = '교육분야 취업자')) +
  scale_y_continuous(name = "전체 취업자",  ## 첫번째 Y축 이름 설정
    sec.axis = sec_axis(trans=~ ./max_ratio, name="교육분야 취업자")) +## 두번째 Y축 변환식과 이름 설정
    scale_x_date(name = '연도') + ## X축 이름 설정
  scale_color_discrete(name = '취업자 종류', breaks = c('전체 취업자', '교육분야 취업자')) + ## 범례 순서 조정과 범례 제목 설정
  theme(legend.position = "bottom") ## 범례 위치 조정

댓글