tidyr로 Pivoting하기

tidyr을 이용해 데이터의 형태를 바꾸는 pivoting에 대해 알아봅시다.
R
dplyr
tidyr
Published

February 3, 2023

이번 시간에는 데이터의 형태를 변환시키는 pivoting을 배워보도록 하겠습니다.

오늘 사용할 패키지는 다음과 같습니다.

library(tidyr)
library(dplyr)
Note

tidyr의 ‘tidy’는 ’정돈하다’ 라는 뜻입니다. 데이터를 정돈하기 위해 사용하는 패키지라고 이해하시면 되겠습니다.

1. Longer: 데이터 길게 늘이기

1) 열 이름에 문자 포함된 경우

pivot_longer() 는 데이터 내의 행의 수를 늘리고, 열의 개수를 줄임으로서 데이터를 길게 만듭니다. 즉 여러 개의 열을 줄여 행으로 바꾸는 과정에서 자연스럽게 데이터의 형태가 길어지는 것을 의미합니다.

relig_incometidyr 패키지에 포함되어 있는 데이터셋으로, 사람들의 종교와 연소득 데이터가 들어있습니다.

pivot_longer() 간단한 예시를 살펴보겠습니다.

relig_income |> 
  pivot_longer(!religion,
               names_to="income",
               values_to = "values")

pivot_longer()에서 사용된 인자는 다음과 같습니다.

  • relig_income: 형태를 변환시킬 데이터

  • cols: 데이터 내에서 길게 변환시킬 열들

  • names_to: 열들이 길게 변환된 뒤, 새로운 열의 이름

  • values_to: 길게 변환된 열들의 데이터가 갖게되는 새로운 열 이름

정리하자면 cols에서는 기존 데이터셋에서 열들의 이름이 들어가는데, 이 열들은 names_to에서 정해준 income이라고 하는 하나의 열로 변환되고, cols에서 선택된 열들의 값들은 values_to에서 정해준 values라고 하는 하나의 열로 변환되는 것입니다.

2) 열 이름에 숫자가 포함된 경우

다음으로 billboard 데이터로 pivot_longer를 진행해보겠습니다. billboard 데이터에는 2000년도의 빌보드 순위 주(week) 단위로 들어있습니다.

이 데이터를 길게 바꾸면 다음과 같습니다.

billboard |> 
  pivot_longer(
    cols=starts_with('wk'),
    names_to='week',
    values_to='rank',
    values_drop_na = T
  )

cols에서 열들을 선택할 때, 규칙이 있는 열들은 dplyr의 select()에서 사용하던 starts_with() 등을 사용할 수 있습니다.

또한 데이터를 길게 변환할 때, values_drop_na를 통해 NA인 데이터들은 제외하였습니다.

데이터를 변환하니 wk~ 열들이 전부 week라는 하나의 열로 변환되었습니다. 그런데 week 열의 데이터는 전부 wk가 들어가있습니다. 몇 주차인지 표현하기 위해서는 숫자만 있어도 될 것 같아 보입니다.

이럴 때, names_prefix 인자를 통해 wk 접두사(prefix)를 없애주도록 하겠습니다.

이 때, names_prefix가 추가되어도, week 의 데이터 유형은 그대로 character입니다. week를 숫자형태로 변환해주려면 names_transform을 이용하면 됩니다.

billboard |> 
  pivot_longer(
    cols=starts_with('wk'),
    names_to='week',
    names_prefix = 'wk',
    names_transform = as.integer,
    values_to='rank',
    values_drop_na = T
  )

3) 열들을 세부적으로 나누기

다음으로는 좀더 까다로운 데이터를 길게 변환해보도록 하겠습니다. tidyrwho 데이터에는 new_sp_m014 부터 newrel_f65 까지, 네 종류의 값들이 열의 이름으로 들어가 있습니다.

  • new_ / new: 새로운 경우들을 값들을 나타냅니다.

  • sp / rel / ep : 진단명

  • m / f: 성별

  • 014 / 1524 / 1524 / 3544 / 4554 / 65 : 나이 범위

이 값들은 규칙을 띈 채로 열 이름으로 되어있기 때문에, name_pattern을 이용해 열 이름에서 추출할 수 있습니다.

who |> 
  pivot_longer(
    cols=new_sp_m014:newrel_f65,
    names_to= c('diagnosis','gender','age'),
    names_pattern = "new_?(.*)_(.)(.*)", # 정규표현식
    values_to="count"
  )
household <- tibble(
  family = 1:5,
  dob_child1 = c('1998-11-26','1996-06-22','2002-07-11','2004-10-10','2000-12-05'),
  dob_child2 = c('2000-01-29',NA,'2004-04-05','2009-08-27','2005-02-28'),
  name_child1 = c('Susan','Mark','Sam','Craig','Parker'),
  name_child2 = c('Jose',NA,'Seth','Khai','Gracie')
)

household |> 
  pivot_longer(
    cols = !family,
    names_to=c('.value',"child"),
    names_sep="_",
    values_drop_na = T,
  )

2. Wider: 데이터 넓게 펼치기

1) Capture-recapture

fish_encounters |> 
  pivot_wider(
    names_from = station,
    values_from = seen
  )

이 데이터에서 결측 값 NA 는 0과 같습니다. 다시 말해, 물고기가 발견된 적이 없다는 것이죠. 그렇기 때문에 NA를 0으로 채워넣을 수 있습니다.

fish_encounters |> 
  pivot_wider(
    names_from = station,
    values_from = seen,
    values_fill = 0
  )

2) Aggregation

warpbreaks |> 
  pivot_wider(
    names_from = c(wool),
    values_from = breaks,
    values_fn = mean
  )
Back to top