ggplot2 이중 Y축 활용법 - 막대그래프와 선그래프 함께 그리기

데이터를 시각화할 때, 서로 다른 단위를 가진 데이터를 한 그래프에 표현해야 하는 경우가 많다. 예를 들어, 한 축에는 월별 매출(₩) 을, 다른 축에는 해당 월의 방문자 수를 표시하고 싶을 때. 이런 경우 ggplot2에서 이중 Y축(sec.axis)을 활용하면 효과적으로 데이터를 비교할 수 있다.

이번 글에서는 ggplot2를 활용하여 바 그래프와 라인 그래프를 한 플롯에 결합하고, 서로 다른 단위를 가진 데이터를 효과적으로 시각화하는 방법을 살펴보려한다.

📋 데이터 준비

yahoo finance 에서 슈드 ETF (SCHD)의 데이터를 다운받았고, 2012-01-01 부터 2025-01-31까지의 데이터로 한정한 다음, 매일 1000원씩 5년간 투자한다고 가정했을 때, 수익률을 그래프로 표현하려 한다. 데이터를 만드는 과정은 생략하고 최종 만들어진 데이터는 대략 아래의 레이아웃이다. rate 가 수익률, cum_amt1 은 누적적립액, close 는 종가이다.

print(table_schd31)

# A tibble: 3,290 × 4
   date       close      rate cum_amt1
   <date>     <dbl>     <dbl>    <dbl>
 1 2012-01-03  8.81 -1.42e-14     1000
 2 2012-01-04  8.81 -1.42e-14     2000
 3 2012-01-05  8.8  -7.57e- 2     3000
 4 2012-01-06  8.76 -3.97e- 1     4000
 5 2012-01-09  8.78 -1.36e- 1     5000
 6 2012-01-10  8.84  4.55e- 1     6000
 7 2012-01-11  8.81  9.81e- 2     7000
 8 2012-01-12  8.81  8.58e- 2     8000
 9 2012-01-13  8.77 -3.28e- 1     9000
10 2012-01-17  8.82  2.17e- 1    10000
# ℹ 3,280 more rows
# ℹ Use `print(n = ...)` to see more rows

📈 그래프 그리기

ggplot2 로 그래프를 하나씩 추가해보자. 우선 최종수익률rate 를 가지고 라인그래프를 그린다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue")
  theme_bw()

여기에 누적적립액 cum_amt1 의 선그래프를 추가한다. ⛔ 그런데, 문제가 생겼다. 2개의 선그래프가 범위가 너무 다르다보니, 아까 최종수익률의 그래프가 일직선처럼 보이게 된다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue") +
  geom_line(aes(date, cum_amt1), colour = "firebrick", size = 1) +
  theme_bw()

🚀 이런 경우, 각각 다른 기준의 y축을 지정해야 한다. 그 때 사용하는게 scale_y_continuous 함수의 sec.axis 파라메터이다. 그런데, 실제값을 그냥 넣으면 아까 그래프와 달라진건 오른쪽 y축이 생겼을뿐 다른게 없다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue") +
  geom_line(aes(date, cum_amt1), colour = "firebrick", size = 1) +
  scale_y_continuous(sec.axis = ~ .) +
  theme_bw()

보정을 해줘야 하는데, aes(date, cum_amt1 / 30000) 와 같이 2개의 y 축 범위를 거의 비슷하게 만드는 작업이 필요하다. 이렇게 하면 문제는 오른쪽 y 축 값이 왜곡된다는 것이다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue") +
  geom_line(aes(date, cum_amt1 / 30000), colour = "firebrick", size = 1) +
  scale_y_continuous(sec.axis = ~ .) +
  theme_bw() +
  theme(axis.title = element_blank())

왜곡된 것을 다시 원복해줘야 하는데, scale_y_continuous 에서 처리해주면 된다. 다시 30000을 곱하면 이제 원래 데이터값으로 보이게 된다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue") +
  geom_line(aes(date, cum_amt1 / 30000), colour = "firebrick", size = 1) +
  scale_y_continuous(sec.axis = ~ . * 30000) +
  theme_bw() +
  theme(axis.title = element_blank())

마지막으로 지수형으로 나오는 y축 값을 일반 정수로 표현하기 위해서, labels 파라메터에 셋팅한다. 두번째 y축의 설정정보를 바꾸기 위해서는, sec_axis 함수를 이용해야 하는 점 참고한다. 그리고 geom_area으로 변경하여 선그래프 아래에 색을 채웠다.

ggplot(table_schd31) +
  geom_line(aes(date, rate), colour ="steelblue") +
  geom_area(aes(date, cum_amt1 / 30000), colour = "firebrick", 
            size = 1, fill = "firebrick", alpha = 0.3) +
  scale_y_continuous(sec.axis = sec_axis(~ . * 30000, labels = scales::label_number())) +
  theme_bw()


더 보면 좋을 글들