library(tidyr)
library(dplyr)이번 시간에는 데이터의 형태를 변환시키는 pivoting을 배워보도록 하겠습니다.
오늘 사용할 패키지는 다음과 같습니다.
tidyr의 ‘tidy’는 ’정돈하다’ 라는 뜻입니다. 데이터를 정돈하기 위해 사용하는 패키지라고 이해하시면 되겠습니다.
1. Longer: 데이터 길게 늘이기
1) 열 이름에 문자 포함된 경우
pivot_longer() 는 데이터 내의 행의 수를 늘리고, 열의 개수를 줄임으로서 데이터를 길게 만듭니다. 즉 여러 개의 열을 줄여 행으로 바꾸는 과정에서 자연스럽게 데이터의 형태가 길어지는 것을 의미합니다.
relig_income 은 tidyr 패키지에 포함되어 있는 데이터셋으로, 사람들의 종교와 연소득 데이터가 들어있습니다.
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) 열들을 세부적으로 나누기
다음으로는 좀더 까다로운 데이터를 길게 변환해보도록 하겠습니다. tidyr 의 who 데이터에는 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
  )