tidyr::pivot_longer 사용법 - 피벗테이블 표로 변환하기

데이터의 형식은 다양하다. 피벗형태일수도 있고, 그냥 테이블과 같은 표형식일 수도 있고, 아니면 한 컬럼에 여러가지 항목들이 구분자로 뭉쳐져 있을 수도 있다. 그 데이터들을 본인이 분석하기 편한 데이터로 만들기 위해 분해하고 다시 조립하는 과정이 있는데, 그중에 피벗형태의 데이터를 테이블 형태로 변경하는 tidyr::pivot_longer 를 살펴보고자 한다.

pivot_longer 사용법

샘플로 데이터를 하나 만들어본다. 각 도시별로 년도별 임의의 통계치가 있다고 가정하고 만들었다. 잘보면 알겠지만, 피벗형태의 데이터이다. 이런 피벗형태의 데이터구조는 사람이 이해하기 쉬운 구조이긴한데, 여러 데이터를 비교하거나 분석하기에 좋은 구조는 아니다.

library(tidyr)
tb1 = tibble(년도 = 2017:2021,
       서울 = seq(100, 140, 10),
       대전 = seq(200, 240, 10),
       대구 = seq(300, 340, 10),
       광주 = seq(400, 440, 10),
       부산 = seq(500, 540, 10)) 

# A tibble: 5 × 6
   년도  서울  대전  대구  광주  부산
  <int> <dbl> <dbl> <dbl> <dbl> <dbl>
1  2017   100   200   300   400   500
2  2018   110   210   310   410   510
3  2019   120   220   320   420   520
4  2020   130   230   330   430   530
5  2021   140   240   340   440   540

이런 피벗형태의 데이터는 tidyr::pivot_longer를 이용하면, 아래로(종의방향으로) 방향을 바꾸어 데이터의 형식을 변경할 수가 있다. 보통 표형태의 데이터로 바뀌게 되면 데이터 row 수가 많아지게 되지만, 다른 데이터를 join 해서 사용하기도 좋고, 특정데이터를 fliter 하거나 group_by 하기도 용이해진다.

pivot_longer(tb1, cols = 서울:부산)
# A tibble: 25 × 3
    년도 name  value
   <int> <chr> <dbl>
 1  2017 서울    100
 2  2017 대전    200
 3  2017 대구    300
 4  2017 광주    400
 5  2017 부산    500
 6  2018 서울    110
 7  2018 대전    210
 8  2018 대구    310
 9  2018 광주    410
10  2018 부산    510
# … with 15 more rows

names_tovalues_to 옵션을 추가로 지정하면, 데이터의 헤더정보로 바인딩되니 참고한다.

pivot_longer(tb1, cols = 서울:부산,
             names_to = "도시",
             values_to = "통계값")

# A tibble: 25 × 3
    년도 도시  통계값
   <int> <chr>  <dbl>
 1  2017 서울     100
 2  2017 대전     200
 3  2017 대구     300
 4  2017 광주     400
 5  2017 부산     500

실제 데이터로 적용해보자

e-나라지표 홈페이지에서 무선통신서비스 가입자 현황자료를 받을 수 있다. 파일링크는 여기를 클릭한다. 받아보면, 파일이 pdf 인데 아래 그림과 같이 피벗형태의 데이터로 되어 있다.

데이터가 엑셀형태가 아니다보니 일일이 손으로 옮겨서 초기 데이터를 만들었다. 이동통신 회선중에 2G/3G/4G/5G 의 연말자료만 가져와서 데이터를 구성했다.

tb1 = tibble(x = 2017:2021,
       y_2G = c(2556242, 1672741, 1020510, 502585, 171930),
       y_3G = c(10661556, 9549356, 7515903, 5604557, 3479622),
       y_4G = c(50440880, 55133681, 55687974, 52555161, 48288764),
       y_5G = c(0,0, 4668154, 11851373, 20915176))

# A tibble: 5 × 5
      x    y_2G     y_3G     y_4G     y_5G
  <int>   <dbl>    <dbl>    <dbl>    <dbl>
1  2017 2556242 10661556 50440880        0
2  2018 1672741  9549356 55133681        0
3  2019 1020510  7515903 55687974  4668154
4  2020  502585  5604557 52555161 11851373
5  2021  171930  3479622 48288764 20915176

이런식의 데이터 구성이라면, 선그래프를 그리기 너무 어려워진다. 아래와 같이 선마다 aes 를 셋팅해야 여러 선그래프를 그릴 수 있다.

ggplot(tb1) +
  geom_line(aes(x, y_2G)) +
  geom_line(aes(x, y_3G)) +
  geom_line(aes(x, y_4G)) +
  geom_line(aes(x, y_5G))

아까 설명한 tidyr::pivot_longer 그룹별로 선그래프를 그리기 편하게끔 데이터 구조를 변경해야 한다. 횡으로 펼쳐진 데이터를 종으로 구조를 바꿔준다. names_tovalues_to 를 입력하면, 헤더정보가 그 이름으로 셋팅된다. 이 두개의 파라메터는 필수가 아니니 필요할때 넣어주면 된다.

tb2 = tb1 %>% pivot_longer(cols = y_2G:y_5G,
                           names_to = "code", 
                           values_to = "count")
tb2
# A tibble: 20 × 3
       x code     count
   <int> <chr>    <dbl>
 1  2017 y_2G   2556242
 2  2017 y_3G  10661556
 3  2017 y_4G  50440880
 4  2017 y_5G         0
 5  2018 y_2G   1672741
 6  2018 y_3G   9549356
 7  2018 y_4G  55133681
 8  2018 y_5G         0
 9  2019 y_2G   1020510
10  2019 y_3G   7515903
11  2019 y_4G  55687974
12  2019 y_5G   4668154
13  2020 y_2G    502585
14  2020 y_3G   5604557
15  2020 y_4G  52555161
16  2020 y_5G  11851373
17  2021 y_2G    171930
18  2021 y_3G   3479622
19  2021 y_4G  48288764
20  2021 y_5G  20915176

이런 데이터의 구조라면, 아래와 같이 그래프를 그리기위한 코딩이 단순해진다.

ggplot(tb2, aes(x, count, colour = code)) +
  geom_line() +
  geom_point()

폰트랑 색상 등을 수정하고나면 아래의 그림도 가능하다.

r  ggplot2 

더 보면 좋을 글들