10 tidyr 패키지로 데이터 정리
9장에서 Tidy Data의 개념에 대해서 설명했다. 여기서는 실제로 사용되는 함수에 관해 좀 더 자세히 설명한다.
10.1 피벗팅(Pivoting)
10.1.1 피벗팅의 기본
우선 tidyr
패키지 cheatsheet에 있는 예시를 보면서 기초를 익히자.
다음과 같은 Untidy data가 있다.
table4a
# A tibble: 3 × 3
country `1999` `2000`
<chr> <dbl> <dbl>
1 Afghanistan 745 2666
2 Brazil 37737 80488
3 China 212258 213766
위 데이터셋은 각 연도별 케이스 수를 나타내는 데이터이다. 값이 되어야할 연도가 열의 이름으로 들어가 있어 이 데이터는 untidy data이다.
이 데이터를 tidy data로 변환하기 위해서는 연도를 값으로 만들어야 하므로, 이 열들 1999
, 2000
을 묶어서 녹인 다음, year
라는 열과 cases
라는 열로 재배열한다.
-
pivot_longer()
함수pivot_longer(df, cols, names_to = "새이름", values_to = "새이름")
- 여러 열 –> (하나로 녹임) –> 펼쳐서 2개의 열로 재배열
- 이 2개의 열에 이름을 부여한다.
- 이름 열은
names_to
인자에, 값 열을values_to
인자에 지정한다.
- 이름 열은
pivot_longer(table4a,
cols = 2:3, names_to = "year",
values_to = "cases"
)
# A tibble: 6 × 3
country year cases
<chr> <chr> <dbl>
1 Afghanistan 1999 745
2 Afghanistan 2000 2666
3 Brazil 1999 37737
4 Brazil 2000 80488
5 China 1999 212258
6 China 2000 213766
다음 table2
는 각 나라의 인구와 케이스 수를 정리하는 데이터셋이다.
table2
# A tibble: 12 × 4
country year type count
<chr> <dbl> <chr> <dbl>
1 Afghanistan 1999 cases 745
2 Afghanistan 1999 population 19987071
3 Afghanistan 2000 cases 2666
4 Afghanistan 2000 population 20595360
5 Brazil 1999 cases 37737
6 Brazil 1999 population 172006362
7 Brazil 2000 cases 80488
8 Brazil 2000 population 174504898
9 China 1999 cases 212258
10 China 1999 population 1272915272
11 China 2000 cases 213766
12 China 2000 population 1280428583
이 데이터셋은 변수로 사용되어야 것들이 값으로 들어가 있다. 이것을 정리하려면 pivot_wider()
함수를 사용한다.
-
pivot_wider()
함수pivot_wider(df, names_from = "이름열", values_from = "값열")
- 2개의 열 –> (하나로 녹임) –> 펼쳐서 여러 열로 재배열
- 이 여러 열에 이름을 부여한다.
- 이름으로 사용되는 값이 있는 열를
names_from
인자에 지정 - 값으로 사용되는 값이 있는 열을
values_from
인자에 지정
- 이름으로 사용되는 값이 있는 열를
pivot_wider(table2,
names_from = type,
values_from = count
)
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
10.1.2 복잡한 경우의 피벗팅: Longer 예시
이 절의 자료는 tidyr
패키지의 Pivoting
비니에트를 참고했다. 이 자료에는 여러 경우의 Untidy data들과 이것을 Tidy data로 변환하는 방법들이 설명되어 있다. 번역, 요약, 주석을 추가했다.
10.1.2.1 문자열 데이터가 열 이름으로 들어간 경우
다음 reglig_incom
를 보자.
relig_income |>
head()
# A tibble: 6 × 11
religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k` `$75-100k`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Agnostic 27 34 60 81 76 137 122
2 Atheist 12 27 37 52 35 70 73
3 Buddhist 27 21 30 34 33 58 62
4 Catholic 418 617 732 670 638 1116 949
5 Don’t kn… 15 14 15 11 10 35 21
6 Evangeli… 575 869 1064 982 881 1486 949
# ℹ 3 more variables: `$100-150k` <dbl>, `>150k` <dbl>,
# `Don't know/refused` <dbl>
이 데이터셋은 각 종교별 소득 분포를 나타내는 데이터이다. 이 데이터셋은 열 이름에 수입 범위가 들어가 있어서 untidy data이다. 이것을 tidy data로 변환하자.
relig_income |>
pivot_longer(
cols = !religion, # 종교 이름이 들어가지 않는 열들을 모두 선택
names_to = "income", # 수입 범위가 들어가는 열의 이름을 "income"으로 지정
values_to = "count" # 수입 범위에 해당하는 값이 들어가는 열의 이름을 "count"로 지정
)
# A tibble: 180 × 3
religion income count
<chr> <chr> <dbl>
1 Agnostic <$10k 27
2 Agnostic $10-20k 34
3 Agnostic $20-30k 60
4 Agnostic $30-40k 81
5 Agnostic $40-50k 76
6 Agnostic $50-75k 137
7 Agnostic $75-100k 122
8 Agnostic $100-150k 109
9 Agnostic >150k 84
10 Agnostic Don't know/refused 96
# ℹ 170 more rows
10.1.2.2 숫자형 데이터가 열 이름으로 들어간 경우
다음 billboard
데이터셋을 보자.
billboard |>
head()
# A tibble: 6 × 79
artist track date.entered wk1 wk2 wk3 wk4 wk5 wk6 wk7 wk8
<chr> <chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2 Pac Baby… 2000-02-26 87 82 72 77 87 94 99 NA
2 2Ge+her The … 2000-09-02 91 87 92 NA NA NA NA NA
3 3 Doors Do… Kryp… 2000-04-08 81 70 68 67 66 57 54 53
4 3 Doors Do… Loser 2000-10-21 76 76 72 69 67 65 55 59
5 504 Boyz Wobb… 2000-04-15 57 34 25 17 17 31 36 49
6 98^0 Give… 2000-08-19 51 39 34 26 26 19 2 2
# ℹ 68 more variables: wk9 <dbl>, wk10 <dbl>, wk11 <dbl>, wk12 <dbl>,
# wk13 <dbl>, wk14 <dbl>, wk15 <dbl>, wk16 <dbl>, wk17 <dbl>, wk18 <dbl>,
# wk19 <dbl>, wk20 <dbl>, wk21 <dbl>, wk22 <dbl>, wk23 <dbl>, wk24 <dbl>,
# wk25 <dbl>, wk26 <dbl>, wk27 <dbl>, wk28 <dbl>, wk29 <dbl>, wk30 <dbl>,
# wk31 <dbl>, wk32 <dbl>, wk33 <dbl>, wk34 <dbl>, wk35 <dbl>, wk36 <dbl>,
# wk37 <dbl>, wk38 <dbl>, wk39 <dbl>, wk40 <dbl>, wk41 <dbl>, wk42 <dbl>,
# wk43 <dbl>, wk44 <dbl>, wk45 <dbl>, wk46 <dbl>, wk47 <dbl>, wk48 <dbl>, …
이 데이터셋은 앨범에 들어 있는 곡의 빌보트 차트 순위를 나타내는 데이터이다. 이 데이터셋은 열 이름에 주간 순위가 들어가 있어서 untidy data이다. 이것을 tidy data로 변환하자.
billboard |>
pivot_longer(
cols = !c(artist, track, date.entered), # 아티스트, 곡, 진입일이 들어가지 않는 열들을 모두 선택
names_to = "week", # 주간 순위가 들어가는 열의 이름을 "week"으로 지정
values_to = "rank" # 주간 순위에 해당하는 값이 들어가는 열의 이름을 "rank"로 지정
)
# A tibble: 24,092 × 5
artist track date.entered week rank
<chr> <chr> <date> <chr> <dbl>
1 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk1 87
2 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk2 82
3 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk3 72
4 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk4 77
5 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk5 87
6 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk6 94
7 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk7 99
8 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk8 NA
9 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk9 NA
10 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk10 NA
# ℹ 24,082 more rows
이 데이터 변환 과정에서 어떤 곡이 어느 주에 빌보드 차트에서 빠진 경우에는 NA
로 표시된다. 이렇게 의미있는 NA
값이 있는 경우에는 사용자가 제거할 수 있게 하는 옵션이 있다. values_drop_na
인자를 TRUE
로 지정하면 된다.
billboard |>
pivot_longer(
cols = !c(artist, track, date.entered), # 아티스트, 곡, 진입일이 들어가지 않는 열들을 모두 선택
names_to = "week", # 주간 순위가 들어가는 열의 이름을 "week"으로 지정
values_to = "rank", # 주간 순위에 해당하는 값이 들어가는 열의 이름을 "rank"로 지정
values_drop_na = TRUE # 값이 없는 경우에는 제거
)
# A tibble: 5,307 × 5
artist track date.entered week rank
<chr> <chr> <date> <chr> <dbl>
1 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk1 87
2 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk2 82
3 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk3 72
4 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk4 77
5 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk5 87
6 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk6 94
7 2 Pac Baby Don't Cry (Keep... 2000-02-26 wk7 99
8 2Ge+her The Hardest Part Of ... 2000-09-02 wk1 91
9 2Ge+her The Hardest Part Of ... 2000-09-02 wk2 87
10 2Ge+her The Hardest Part Of ... 2000-09-02 wk3 92
# ℹ 5,297 more rows
위 결과를 보면 week
열에 wk1
등과 같이 문자열로 되어 있는데, 이것은 숫자형 데이터가 되어야 맞을 것이다. 그래야 어떤 곡이 몇 주 동안 빌보드에 남아있는지 등을 계산할 수 있다.
이런 경우에 wk1
에서 wk
를 제거할 수 있는 옵션이 있다. names_prefix
인자가 그것이다.
billboard |>
pivot_longer(
cols = !c(artist, track, date.entered), # 아티스트, 곡, 진입일이 들어가지 않는 열들을 모두 선택
names_to = "week", # 주간 순위가 들어가는 열의 이름을 "week"으로 지정
names_prefix = "wk", # "wk" 문자열을 제거
values_to = "rank", # 주간 순위에 해당하는 값이 들어가는 열의 이름을 "rank"로 지정
values_drop_na = TRUE # 값이 없는 경우에는 제거
)
# A tibble: 5,307 × 5
artist track date.entered week rank
<chr> <chr> <date> <chr> <dbl>
1 2 Pac Baby Don't Cry (Keep... 2000-02-26 1 87
2 2 Pac Baby Don't Cry (Keep... 2000-02-26 2 82
3 2 Pac Baby Don't Cry (Keep... 2000-02-26 3 72
4 2 Pac Baby Don't Cry (Keep... 2000-02-26 4 77
5 2 Pac Baby Don't Cry (Keep... 2000-02-26 5 87
6 2 Pac Baby Don't Cry (Keep... 2000-02-26 6 94
7 2 Pac Baby Don't Cry (Keep... 2000-02-26 7 99
8 2Ge+her The Hardest Part Of ... 2000-09-02 1 91
9 2Ge+her The Hardest Part Of ... 2000-09-02 2 87
10 2Ge+her The Hardest Part Of ... 2000-09-02 3 92
# ℹ 5,297 more rows
위 결과를 잘 보면 week
열이 아직도 문자열로 되어 있다. 이것을 숫자형 데이터로 변환할 수 있다.
billboard |>
pivot_longer(
cols = !c(artist, track, date.entered), # 아티스트, 곡, 진입일이 들어가지 않는 열들을 모두 선택
names_to = "week", # 주간 순위가 들어가는 열의 이름을 "week"으로 지정
names_prefix = "wk", # "wk" 문자열을 제거
values_to = "rank", # 주간 순위에 해당하는 값이 들어가는 열의 이름을 "rank"로 지정
values_drop_na = TRUE # 값이 없는 경우에는 제거
) |>
mutate(week = as.numeric(week))
# A tibble: 5,307 × 5
artist track date.entered week rank
<chr> <chr> <date> <dbl> <dbl>
1 2 Pac Baby Don't Cry (Keep... 2000-02-26 1 87
2 2 Pac Baby Don't Cry (Keep... 2000-02-26 2 82
3 2 Pac Baby Don't Cry (Keep... 2000-02-26 3 72
4 2 Pac Baby Don't Cry (Keep... 2000-02-26 4 77
5 2 Pac Baby Don't Cry (Keep... 2000-02-26 5 87
6 2 Pac Baby Don't Cry (Keep... 2000-02-26 6 94
7 2 Pac Baby Don't Cry (Keep... 2000-02-26 7 99
8 2Ge+her The Hardest Part Of ... 2000-09-02 1 91
9 2Ge+her The Hardest Part Of ... 2000-09-02 2 87
10 2Ge+her The Hardest Part Of ... 2000-09-02 3 92
# ℹ 5,297 more rows
그런데 pivot_longer()
함수에서 이 작업을 해주는 옵션이 있다. pivot_longer()
함수는 names_to
에 의해서 생성되는 열들을 디폴트로 문자열 타입으로 만들고, values_to
에 의해서 생성되는 열들의 타입은 입력되는 열에서 가장 흔한 타입이 되게 한다. 이 과정을 names_transform
, values_transform
인자를 사용하여 변경할 수 있다.
billboard |>
pivot_longer(
cols = !c(artist, track, date.entered), # 아티스트, 곡, 진입일이 들어가지 않는 열들을 모두 선택
names_to = "week", # 주간 순위가 들어가는 열의 이름을 "week"으로 지정
values_to = "rank", # 주간 순위에 해당하는 값이 들어가는 열의 이름을 "rank"로 지정
names_prefix = "wk", # "wk" 문자열을 제거
names_transform = list(week = as.numeric), # 열의 이름을 지정할 때 사용되는 타입을 integer로 지정
)
# A tibble: 24,092 × 5
artist track date.entered week rank
<chr> <chr> <date> <dbl> <dbl>
1 2 Pac Baby Don't Cry (Keep... 2000-02-26 1 87
2 2 Pac Baby Don't Cry (Keep... 2000-02-26 2 82
3 2 Pac Baby Don't Cry (Keep... 2000-02-26 3 72
4 2 Pac Baby Don't Cry (Keep... 2000-02-26 4 77
5 2 Pac Baby Don't Cry (Keep... 2000-02-26 5 87
6 2 Pac Baby Don't Cry (Keep... 2000-02-26 6 94
7 2 Pac Baby Don't Cry (Keep... 2000-02-26 7 99
8 2 Pac Baby Don't Cry (Keep... 2000-02-26 8 NA
9 2 Pac Baby Don't Cry (Keep... 2000-02-26 9 NA
10 2 Pac Baby Don't Cry (Keep... 2000-02-26 10 NA
# ℹ 24,082 more rows
10.1.2.3 여러 개의 변수들이 열 이름에 포함된 경우
다음 who
데이터셋을 보자.
who |>
head()
# A tibble: 6 × 60
country iso2 iso3 year new_sp_m014 new_sp_m1524 new_sp_m2534 new_sp_m3544
<chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Afghanis… AF AFG 1980 NA NA NA NA
2 Afghanis… AF AFG 1981 NA NA NA NA
3 Afghanis… AF AFG 1982 NA NA NA NA
4 Afghanis… AF AFG 1983 NA NA NA NA
5 Afghanis… AF AFG 1984 NA NA NA NA
6 Afghanis… AF AFG 1985 NA NA NA NA
# ℹ 52 more variables: new_sp_m4554 <dbl>, new_sp_m5564 <dbl>,
# new_sp_m65 <dbl>, new_sp_f014 <dbl>, new_sp_f1524 <dbl>,
# new_sp_f2534 <dbl>, new_sp_f3544 <dbl>, new_sp_f4554 <dbl>,
# new_sp_f5564 <dbl>, new_sp_f65 <dbl>, new_sn_m014 <dbl>,
# new_sn_m1524 <dbl>, new_sn_m2534 <dbl>, new_sn_m3544 <dbl>,
# new_sn_m4554 <dbl>, new_sn_m5564 <dbl>, new_sn_m65 <dbl>,
# new_sn_f014 <dbl>, new_sn_f1524 <dbl>, new_sn_f2534 <dbl>, …
names(who)
[1] "country" "iso2" "iso3" "year" "new_sp_m014"
[6] "new_sp_m1524" "new_sp_m2534" "new_sp_m3544" "new_sp_m4554" "new_sp_m5564"
[11] "new_sp_m65" "new_sp_f014" "new_sp_f1524" "new_sp_f2534" "new_sp_f3544"
[16] "new_sp_f4554" "new_sp_f5564" "new_sp_f65" "new_sn_m014" "new_sn_m1524"
[21] "new_sn_m2534" "new_sn_m3544" "new_sn_m4554" "new_sn_m5564" "new_sn_m65"
[26] "new_sn_f014" "new_sn_f1524" "new_sn_f2534" "new_sn_f3544" "new_sn_f4554"
[31] "new_sn_f5564" "new_sn_f65" "new_ep_m014" "new_ep_m1524" "new_ep_m2534"
[36] "new_ep_m3544" "new_ep_m4554" "new_ep_m5564" "new_ep_m65" "new_ep_f014"
[41] "new_ep_f1524" "new_ep_f2534" "new_ep_f3544" "new_ep_f4554" "new_ep_f5564"
[46] "new_ep_f65" "newrel_m014" "newrel_m1524" "newrel_m2534" "newrel_m3544"
[51] "newrel_m4554" "newrel_m5564" "newrel_m65" "newrel_f014" "newrel_f1524"
[56] "newrel_f2534" "newrel_f3544" "newrel_f4554" "newrel_f5564" "newrel_f65"
이 데이터셋에서 new_
또는 new
는 새로운 케이이스를 의미한다. m
rel
, ep
는 진단방법을 의미하고 m
, f
는 성별을 의미한다. 1524
, 65
등은 나이 범위를 의미한다.
이 데이터셋을 pivot_longer()
함수를 사용하여 tidy data로 변환해 보자. 먼저 names_to
에 의해서 생성되는 열들의 이름을 지정한다. 또 names_pattern
인자를 사용하여 열 이름에 포함된 문자열을 패턴으로 지정한다.
사실 이 기능을 사용하려면 R 언어의 정규 표현식을 알아야 한다. 정규 표현식은 문자열의 패턴을 지정하는 표현식이다. 관심이 있는 경우는 R for Data Science (2e) 15장 Regular Expressions 장을 참고하라.
names_pattern
인자에 사용되는 정규 표현식은 다음과 같다.
-
new_?(.*)_(.)(.*)
-
new_
또는new
:_?
라고 했고?
는 앞의 문자가 0번 또는 1번 나오는 것을 의미한다. -
(.*)
는 하나의 정규 표현식의 그룹(group)인데, 그 안에.*
가 들어가 있어 다음_
문자가 나오기 전까지 모든 문자들을 의미한다. -
(.)
도 그룹이고,.
은 하나의 alphanumeric 문자을 의미한다. -
(.*)
도 그룹으로, 모든 문자열을 의미한다.
-
여기서 사용된 그룹은 names_to
에서 잡는다.
who |>
pivot_longer(
cols = !c(country, iso2, iso3, year), # 나라, 국제 표준 국가 코드, 국제 표준 국가 코드, 연도가 들어가지 않는 열들을 모두 선택
names_to = c("diagnosis", "gender", "age"), # 진단방법, 성별, 나이 범위가 들어가는 열의 이름을 지정
names_pattern = "new_?(.*)_(.)(.*)",
values_to = "count" # 값이 들어가는 열의 이름을 "count"로 지정
)
# A tibble: 405,440 × 8
country iso2 iso3 year diagnosis gender age count
<chr> <chr> <chr> <dbl> <chr> <chr> <chr> <dbl>
1 Afghanistan AF AFG 1980 sp m 014 NA
2 Afghanistan AF AFG 1980 sp m 1524 NA
3 Afghanistan AF AFG 1980 sp m 2534 NA
4 Afghanistan AF AFG 1980 sp m 3544 NA
5 Afghanistan AF AFG 1980 sp m 4554 NA
6 Afghanistan AF AFG 1980 sp m 5564 NA
7 Afghanistan AF AFG 1980 sp m 65 NA
8 Afghanistan AF AFG 1980 sp f 014 NA
9 Afghanistan AF AFG 1980 sp f 1524 NA
10 Afghanistan AF AFG 1980 sp f 2534 NA
# ℹ 405,430 more rows
앞에서도 설명했지만 names_to
로 생성되는 열의 데이터타입은 문자열이다. 이것을 names_transform
인자를 사용하여 팩터로 변환하였다.
who |>
pivot_longer(
cols = !c(country, iso2, iso3, year), # 나라, 국제 표준 국가 코드, 국제 표준 국가 코드, 연도가 들어가지 않는 열들을 모두 선택
names_to = c("diagnosis", "gender", "age"), # 진단방법, 성별, 나이 범위가 들어가는 열의 이름을 지정
names_pattern = "new_?(.*)_(.)(.*)",
names_transform = list(
diagnosis = as.factor,
gender = as.factor,
age = as.factor
),
values_to = "count" # 값이 들어가는 열의 이름을 "count"로 지정
) |>
rename(
age_group = age
) |>
tail()
# A tibble: 6 × 8
country iso2 iso3 year diagnosis gender age_group count
<chr> <chr> <chr> <dbl> <fct> <fct> <fct> <dbl>
1 Zimbabwe ZW ZWE 2013 rel f 1524 2069
2 Zimbabwe ZW ZWE 2013 rel f 2534 4649
3 Zimbabwe ZW ZWE 2013 rel f 3544 3526
4 Zimbabwe ZW ZWE 2013 rel f 4554 1453
5 Zimbabwe ZW ZWE 2013 rel f 5564 811
6 Zimbabwe ZW ZWE 2013 rel f 65 725
10.1.2.4 하나의 행에 여러 관측이 들어간 경우
다음 household
데이터셋을 보자.
household
# A tibble: 5 × 5
family dob_child1 dob_child2 name_child1 name_child2
<int> <date> <date> <chr> <chr>
1 1 1998-11-26 2000-01-29 Susan Jose
2 2 1996-06-22 NA Mark <NA>
3 3 2002-07-11 2004-04-05 Sam Seth
4 4 2004-10-10 2009-08-27 Craig Khai
5 5 2000-12-05 2005-02-28 Parker Gracie
이 데이터셋은 하나의 행에 자녀의 출생일과 그 이름을 정리할 것인데, 이것을 하나의 열로 모아서 표현한 것이다.
이 경우 names_sep
인자를 사용하여 열을 분리하고, names_to
인자에 .value
라는 특수한 값을 지정하면 이 부분에 해당되는 부분을 열의 이름으로 지정한다. dob_child1
, name_child2
과 같은 열이 있을 때 names_sep = "_"
로 지정했기 때문에 dob
와 name
이 .value
에 들어가게 되고, child1
, child2
부분이 child
에 들어가게 된다.
household |>
pivot_longer(
cols = !family,
names_to = c(".value", "child"),
names_sep = "_",
values_drop_na = TRUE
)
# A tibble: 9 × 4
family child dob name
<int> <chr> <date> <chr>
1 1 child1 1998-11-26 Susan
2 1 child2 2000-01-29 Jose
3 2 child1 1996-06-22 Mark
4 3 child1 2002-07-11 Sam
5 3 child2 2004-04-05 Seth
6 4 child1 2004-10-10 Craig
7 4 child2 2009-08-27 Khai
8 5 child1 2000-12-05 Parker
9 5 child2 2005-02-28 Gracie
10.1.3 복잡한 경우의 피벗팅: Wider 예시
다음 fish_encounters
데이터셋은 물고기에 태그를 붙이고, 여러 지점(station
)에서 수중 센서를 사용해 해당 물고기의 이동이 감지되었는지를 기록한 데이터이다.
fish_encounters
# A tibble: 114 × 3
fish station seen
<fct> <fct> <int>
1 4842 Release 1
2 4842 I80_1 1
3 4842 Lisbon 1
4 4842 Rstr 1
5 4842 Base_TD 1
6 4842 BCE 1
7 4842 BCW 1
8 4842 BCE2 1
9 4842 BCW2 1
10 4842 MAE 1
# ℹ 104 more rows
이 경우 어떤 물고기가 어떤 지점에서 감지되었는 정리해 보고 싶을 수 있다. 이 경우 pivot_wider()
함수를 사용할 수 있다. names_from
에 열로 올려 놓을 이름을 지정하다.
fish_encounters |>
pivot_wider(
names_from = station,
values_from = seen
)
# A tibble: 19 × 12
fish Release I80_1 Lisbon Rstr Base_TD BCE BCW BCE2 BCW2 MAE MAW
<fct> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 4842 1 1 1 1 1 1 1 1 1 1 1
2 4843 1 1 1 1 1 1 1 1 1 1 1
3 4844 1 1 1 1 1 1 1 1 1 1 1
4 4845 1 1 1 1 1 NA NA NA NA NA NA
5 4847 1 1 1 NA NA NA NA NA NA NA NA
6 4848 1 1 1 1 NA NA NA NA NA NA NA
7 4849 1 1 NA NA NA NA NA NA NA NA NA
8 4850 1 1 NA 1 1 1 1 NA NA NA NA
9 4851 1 1 NA NA NA NA NA NA NA NA NA
10 4854 1 1 NA NA NA NA NA NA NA NA NA
11 4855 1 1 1 1 1 NA NA NA NA NA NA
12 4857 1 1 1 1 1 1 1 1 1 NA NA
13 4858 1 1 1 1 1 1 1 1 1 1 1
14 4859 1 1 1 1 1 NA NA NA NA NA NA
15 4861 1 1 1 1 1 1 1 1 1 1 1
16 4862 1 1 1 1 1 1 1 1 1 NA NA
17 4863 1 1 NA NA NA NA NA NA NA NA NA
18 4864 1 1 NA NA NA NA NA NA NA NA NA
19 4865 1 1 1 NA NA NA NA NA NA NA NA
이 경우 감지되지 않은 경우에는 NA
로 표시되는데, 이것을 0
으로 채워 넣고 싶을 수 있다. 이 경우 values_fill
인자를 사용하면 된다.
fish_encounters |>
pivot_wider(
names_from = station,
values_from = seen,
values_fill = 0
)
# A tibble: 19 × 12
fish Release I80_1 Lisbon Rstr Base_TD BCE BCW BCE2 BCW2 MAE MAW
<fct> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
1 4842 1 1 1 1 1 1 1 1 1 1 1
2 4843 1 1 1 1 1 1 1 1 1 1 1
3 4844 1 1 1 1 1 1 1 1 1 1 1
4 4845 1 1 1 1 1 0 0 0 0 0 0
5 4847 1 1 1 0 0 0 0 0 0 0 0
6 4848 1 1 1 1 0 0 0 0 0 0 0
7 4849 1 1 0 0 0 0 0 0 0 0 0
8 4850 1 1 0 1 1 1 1 0 0 0 0
9 4851 1 1 0 0 0 0 0 0 0 0 0
10 4854 1 1 0 0 0 0 0 0 0 0 0
11 4855 1 1 1 1 1 0 0 0 0 0 0
12 4857 1 1 1 1 1 1 1 1 1 0 0
13 4858 1 1 1 1 1 1 1 1 1 1 1
14 4859 1 1 1 1 1 0 0 0 0 0 0
15 4861 1 1 1 1 1 1 1 1 1 1 1
16 4862 1 1 1 1 1 1 1 1 1 0 0
17 4863 1 1 0 0 0 0 0 0 0 0 0
18 4864 1 1 0 0 0 0 0 0 0 0 0
19 4865 1 1 1 0 0 0 0 0 0 0 0
여러 조합으로 구성된 데이터가 있다고 해 보자. 다음 코드에서 .
은 파이프 연산자를 %>%
를 사용할 때 앞의 데이터프레임을 대신하는 표현식이다. 그래서 |>
연산자를 사용할 때는 작동하지 않는다.
production <-
expand_grid(
product = c("A", "B"),
country = c("AI", "EI"),
year = 2000:2014
) %>%
as_tibble() %>%
mutate(production = rnorm(nrow(.)))
production
# A tibble: 60 × 4
product country year production
<chr> <chr> <int> <dbl>
1 A AI 2000 0.226
2 A AI 2001 -2.26
3 A AI 2002 0.729
4 A AI 2003 1.59
5 A AI 2004 0.126
6 A AI 2005 0.0442
7 A AI 2006 -0.849
8 A AI 2007 -0.0277
9 A AI 2008 0.0537
10 A AI 2009 -0.847
# ℹ 50 more rows
glimpse(production)
Rows: 60
Columns: 4
$ product <chr> "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A",…
$ country <chr> "AI", "AI", "AI", "AI", "AI", "AI", "AI", "AI", "AI", "AI",…
$ year <int> 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,…
$ production <dbl> 0.22620776, -2.26375359, 0.72890163, 1.59301748, 0.12635456…
이 데이터셋을 연도별로 정리해서 보여줄 필요가 있을 수 있고 다음과 같은 코드를 사용할 수 있다.
production |>
pivot_wider(
names_from = c(product, country),
values_from = production
)
# A tibble: 15 × 5
year A_AI A_EI B_AI B_EI
<int> <dbl> <dbl> <dbl> <dbl>
1 2000 0.226 -1.36 0.251 0.176
2 2001 -2.26 0.634 -0.791 -0.936
3 2002 0.729 -1.09 -1.30 -0.294
4 2003 1.59 1.23 -1.55 0.546
5 2004 0.126 -1.08 -0.749 0.672
6 2005 0.0442 0.753 -1.02 0.643
7 2006 -0.849 -0.0387 -1.06 -0.0511
8 2007 -0.0277 -0.430 -0.616 1.41
9 2008 0.0537 -0.179 -1.32 0.133
10 2009 -0.847 -1.16 -0.613 -0.392
11 2010 -1.28 -1.34 1.41 -1.00
12 2011 0.0374 -0.931 0.170 -1.39
13 2012 -1.02 -1.33 -0.631 -1.28
14 2013 0.0155 -0.252 0.176 1.90
15 2014 2.27 2.74 0.245 1.68
이런 경우 이름을 _
로 연결하여 만들고 있다. 이것을 바꾸려면 names_sep
인자를 사용한다. names_prefix
인자를 사용하면 접두사를 붙일 수 있다.
production |>
pivot_wider(
names_from = c(product, country),
values_from = production,
names_sep = ".",
names_prefix = "production."
)
# A tibble: 15 × 5
year production.A.AI production.A.EI production.B.AI production.B.EI
<int> <dbl> <dbl> <dbl> <dbl>
1 2000 0.226 -1.36 0.251 0.176
2 2001 -2.26 0.634 -0.791 -0.936
3 2002 0.729 -1.09 -1.30 -0.294
4 2003 1.59 1.23 -1.55 0.546
5 2004 0.126 -1.08 -0.749 0.672
6 2005 0.0442 0.753 -1.02 0.643
7 2006 -0.849 -0.0387 -1.06 -0.0511
8 2007 -0.0277 -0.430 -0.616 1.41
9 2008 0.0537 -0.179 -1.32 0.133
10 2009 -0.847 -1.16 -0.613 -0.392
11 2010 -1.28 -1.34 1.41 -1.00
12 2011 0.0374 -0.931 0.170 -1.39
13 2012 -1.02 -1.33 -0.631 -1.28
14 2013 0.0155 -0.252 0.176 1.90
15 2014 2.27 2.74 0.245 1.68
10.2 정리
- Pivoting 비니에트에 있는 사례들을 모두 정리한 것은 아니다. 더 많은 사례를 보려면 이 링크를 참고한다.