{dplyr}
데이터를 R
로 가져오려고 할 때, 데이터 시각화 및 데이터 모델링에 필요한, 원하는 형태의 데이터를 쉽게 다운받을 수 있는 경우는 드뭅니다. {dplyr}
패키지는 데이터를 필요한 형태로 변환(transform)하거나 조작(manipulation)할 수 있는 일련의 함수 집합을 제공합니다.
“dplyr is a grammar of data manipulation, providing a consistent set of verbs that help you solve the most common data manipulation challenges:
mutate() adds new variables that are functions of existing variables
select() picks variables based on their names.
filter() picks cases based on their values.
summarise() reduces multiple values down to a single summary.
arrange() changes the ordering of the rows.
Tibbles
Base R에서는 데이터를 저장하기 위해 데이터 프레임을 사용하는 경우가 많습니다. 티블은 Base R에서 데이터 프레임의 {tidyverse}
버전입니다. {tidyverse}
함수는 데이터 프레임과 티블을 모두 받습니다. 종종 as_tibble()
을 사용하여 데이터 프레임을 티블로 변환하고 싶을 수 있습니다:
# Base R에 내장된 데이터 프레임인 iris를 살펴보자
as_tibble (iris)
# A tibble: 150 × 5
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
<dbl> <dbl> <dbl> <dbl> <fct>
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
7 4.6 3.4 1.4 0.3 setosa
8 5 3.4 1.5 0.2 setosa
9 4.4 2.9 1.4 0.2 setosa
10 4.9 3.1 1.5 0.1 setosa
# ℹ 140 more rows
티블 데이터 유형에 대한 더 자세한 내용을 알고 싶다면 여기 의 링크를 확인해 보세요.
Select Columns with select()
select()
함수는 데이터셋의 열을 특정하여 선택합니다. select()
와 같은 경우 다른 패키지에서도 사용할 수 있는 보편적이고 흔한 함수명이기 때문에, 충돌이 발생하는 것을 방지하기 위하여 dplyr
패키지에 속한 select()
함수를 가져오라고 특정해줄 필요가 있습니다. 패키지를 특정하는 것은 ::
를 이용해 가능합니다. 즉, dplyr::select()
는 select()
함수를 사용하되 {dplyr}
에 속한 select()
함수를 가져오라는 의미입니다.
# nycflight13 패키지에서 flights 데이터를 사용해봅시다.
library (nycflights13)
# names() 함수는 데이터셋의 열 이름을 나타냅니다.
names (flights)
[1] "year" "month" "day" "dep_time"
[5] "sched_dep_time" "dep_delay" "arr_time" "sched_arr_time"
[9] "arr_delay" "carrier" "flight" "tailnum"
[13] "origin" "dest" "air_time" "distance"
[17] "hour" "minute" "time_hour"
# 열 이름을 사용하여 데이터셋에서 필요한 열 들을 선택합시다.
flights |> select (year, month, day)
# A tibble: 336,776 × 3
year month day
<int> <int> <int>
1 2013 1 1
2 2013 1 1
3 2013 1 1
4 2013 1 1
5 2013 1 1
6 2013 1 1
7 2013 1 1
8 2013 1 1
9 2013 1 1
10 2013 1 1
# ℹ 336,766 more rows
# year와 day 사이의 모든 열을 선택해봅시다
flights |> select (year: day)
# A tibble: 336,776 × 3
year month day
<int> <int> <int>
1 2013 1 1
2 2013 1 1
3 2013 1 1
4 2013 1 1
5 2013 1 1
6 2013 1 1
7 2013 1 1
8 2013 1 1
9 2013 1 1
10 2013 1 1
# ℹ 336,766 more rows
!
는 일련의 변수의 여집합(complement)을 의미합니다.
# year와 day 사이의 열을 제외한 모든 변수를 선택하라
flights |> select (! (year: day))
# A tibble: 336,776 × 16
dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier
<int> <int> <dbl> <int> <int> <dbl> <chr>
1 517 515 2 830 819 11 UA
2 533 529 4 850 830 20 UA
3 542 540 2 923 850 33 AA
4 544 545 -1 1004 1022 -18 B6
5 554 600 -6 812 837 -25 DL
6 554 558 -4 740 728 12 UA
7 555 600 -5 913 854 19 B6
8 557 600 -3 709 723 -14 EV
9 557 600 -3 838 846 -8 B6
10 558 600 -2 753 745 8 AA
# ℹ 336,766 more rows
# ℹ 9 more variables: flight <int>, tailnum <chr>, origin <chr>, dest <chr>,
# air_time <dbl>, distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
선택 도우미 함수(selection helper functions)는 이름에 있는 패턴을 확인하여 그에 일치하는 변수를 선택합니다:
starts_with()
: 특정 문자로 시작하는 열을 모두 선택합니다.
ends_with()
: 특정 문자로 끝나는 열을 모두 선택합니다.
contains()
: 특정 문자열을 포함하는 열을 모두 선택합니다.
matches()
: 특정 정규표현식의 조건에 일치하는 열을 모두 선택합니다.
num_range()
: x01, x02, x03과 같은 숫자 범위가 일치하는 열을 모두 선택합니다.
# "dep"로 시작하는 모든 열을 선택합니다
flights |> select (starts_with ("dep" ))
# A tibble: 336,776 × 2
dep_time dep_delay
<int> <dbl>
1 517 2
2 533 4
3 542 2
4 544 -1
5 554 -6
6 554 -4
7 555 -5
8 557 -3
9 557 -3
10 558 -2
# ℹ 336,766 more rows
# "time"으로 끝나는 모든 열을 선택합니다
flights |> select (ends_with ("time" ))
# A tibble: 336,776 × 5
dep_time sched_dep_time arr_time sched_arr_time air_time
<int> <int> <int> <int> <dbl>
1 517 515 830 819 227
2 533 529 850 830 227
3 542 540 923 850 160
4 544 545 1004 1022 183
5 554 600 812 837 116
6 554 558 740 728 150
7 555 600 913 854 158
8 557 600 709 723 53
9 557 600 838 846 140
10 558 600 753 745 138
# ℹ 336,766 more rows
# "time"을 포함하는 모든 열을 선택합니다
flights |> select (contains ("time" ))
# A tibble: 336,776 × 6
dep_time sched_dep_time arr_time sched_arr_time air_time time_hour
<int> <int> <int> <int> <dbl> <dttm>
1 517 515 830 819 227 2013-01-01 05:00:00
2 533 529 850 830 227 2013-01-01 05:00:00
3 542 540 923 850 160 2013-01-01 05:00:00
4 544 545 1004 1022 183 2013-01-01 05:00:00
5 554 600 812 837 116 2013-01-01 06:00:00
6 554 558 740 728 150 2013-01-01 05:00:00
7 555 600 913 854 158 2013-01-01 06:00:00
8 557 600 709 723 53 2013-01-01 06:00:00
9 557 600 838 846 140 2013-01-01 06:00:00
10 558 600 753 745 138 2013-01-01 06:00:00
# ℹ 336,766 more rows
# "dep"으로 시작하면서 "time"을 포함하는 year와 day 사이의 모든 열을 선택합니다.
flights |> select (starts_with ("dep" ), contains ("time" ), year: day)
# A tibble: 336,776 × 10
dep_time dep_delay sched_dep_time arr_time sched_arr_time air_time
<int> <dbl> <int> <int> <int> <dbl>
1 517 2 515 830 819 227
2 533 4 529 850 830 227
3 542 2 540 923 850 160
4 544 -1 545 1004 1022 183
5 554 -6 600 812 837 116
6 554 -4 558 740 728 150
7 555 -5 600 913 854 158
8 557 -3 600 709 723 53
9 557 -3 600 838 846 140
10 558 -2 600 753 745 138
# ℹ 336,766 more rows
# ℹ 4 more variables: time_hour <dttm>, year <int>, month <int>, day <int>
# 1번째, 3번째, 5번째 열을 선택합니다
flights |> select (c (1 ,3 ,5 ))
# A tibble: 336,776 × 3
year day sched_dep_time
<int> <int> <int>
1 2013 1 515
2 2013 1 529
3 2013 1 540
4 2013 1 545
5 2013 1 600
6 2013 1 558
7 2013 1 600
8 2013 1 600
9 2013 1 600
10 2013 1 600
# ℹ 336,766 more rows
이번에는 {tidyverse}
내의 billboard
데이터셋을 사용해보겠습니다. billboard
데이터셋은 빌보드 차트의 2000곡 중에서 상위 100곡에 대한 랭킹 정보를 제공합니다.
# A tibble: 317 × 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 D… Kryp… 2000-04-08 81 70 68 67 66 57 54 53
4 3 Doors D… 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
7 A*Teens Danc… 2000-07-08 97 97 96 95 100 NA NA NA
8 Aaliyah I Do… 2000-01-29 84 62 51 41 38 35 35 38
9 Aaliyah Try … 2000-03-18 59 53 38 28 21 18 16 14
10 Adams, Yo… Open… 2000-08-26 76 76 74 69 68 67 61 58
# ℹ 307 more rows
# ℹ 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>, …
# names()로 데이터셋의 열들의 이름을 반환합니다
names (billboard)
[1] "artist" "track" "date.entered" "wk1" "wk2"
[6] "wk3" "wk4" "wk5" "wk6" "wk7"
[11] "wk8" "wk9" "wk10" "wk11" "wk12"
[16] "wk13" "wk14" "wk15" "wk16" "wk17"
[21] "wk18" "wk19" "wk20" "wk21" "wk22"
[26] "wk23" "wk24" "wk25" "wk26" "wk27"
[31] "wk28" "wk29" "wk30" "wk31" "wk32"
[36] "wk33" "wk34" "wk35" "wk36" "wk37"
[41] "wk38" "wk39" "wk40" "wk41" "wk42"
[46] "wk43" "wk44" "wk45" "wk46" "wk47"
[51] "wk48" "wk49" "wk50" "wk51" "wk52"
[56] "wk53" "wk54" "wk55" "wk56" "wk57"
[61] "wk58" "wk59" "wk60" "wk61" "wk62"
[66] "wk63" "wk64" "wk65" "wk66" "wk67"
[71] "wk68" "wk69" "wk70" "wk71" "wk72"
[76] "wk73" "wk74" "wk75" "wk76"
billboard |> select (num_range ("wk" , 20 : 23 ))
# A tibble: 317 × 4
wk20 wk21 wk22 wk23
<dbl> <dbl> <dbl> <dbl>
1 NA NA NA NA
2 NA NA NA NA
3 14 12 7 6
4 70 NA NA NA
5 NA NA NA NA
6 94 NA NA NA
7 NA NA NA NA
8 86 NA NA NA
9 4 5 5 6
10 89 NA NA NA
# ℹ 307 more rows
Filter Rows with filter()
filter()
는 값에 따라 관측치들을 필터링합니다. 필터링할 여러 인수는 논리 연산자를 사용하여 결합됩니다.
기본적으로 여러 조건은 &
와 결합됩니다.
# 1월에 출발한 항공편으로 필터링해보겠습니다.
# month == 1 & day == 1
flights |> dplyr:: filter (month == 1 & day == 1 )
# A tibble: 842 × 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# ℹ 832 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
# 11월 또는 12월에 출발하는 비행편으로 필터링해봅시다
flights |> dplyr:: filter (month == 11 | month == 12 )
# A tibble: 55,403 × 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 11 1 5 2359 6 352 345
2 2013 11 1 35 2250 105 123 2356
3 2013 11 1 455 500 -5 641 651
4 2013 11 1 539 545 -6 856 827
5 2013 11 1 542 545 -3 831 855
6 2013 11 1 549 600 -11 912 923
7 2013 11 1 550 600 -10 705 659
8 2013 11 1 554 600 -6 659 701
9 2013 11 1 554 600 -6 826 827
10 2013 11 1 554 600 -6 749 751
# ℹ 55,393 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
# IAH로 도착하는 항공편을 모두 필터링해봅시다
flights |> dplyr:: filter (dest == "IAH" )
# A tibble: 7,198 × 19
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 623 627 -4 933 932
4 2013 1 1 728 732 -4 1041 1038
5 2013 1 1 739 739 0 1104 1038
6 2013 1 1 908 908 0 1228 1219
7 2013 1 1 1028 1026 2 1350 1339
8 2013 1 1 1044 1045 -1 1352 1351
9 2013 1 1 1114 900 134 1447 1222
10 2013 1 1 1205 1200 5 1503 1505
# ℹ 7,188 more rows
# ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>
Add New Variables with mutate()
mutate()
는 새로운 변수를 만드는 함수입니다. mutate()
는 변환을 반복적으로 실행하여 이후 변환이 이전 변환에서 생성한 열을 사용할 수 있도록 합니다. 즉, 여기서는 gain
, hours
를 mutate()
내에서 먼저 만들었기 때문에 그 만들어진 변수들을 이용하여 gain_per_hour
변수를 생성할 수 있는 것입니다.
flights |>
mutate (gain = arr_delay - dep_delay,
hours = air_time / 60 ,
gain_per_hour = gain / hours)
# A tibble: 336,776 × 22
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
<int> <int> <int> <int> <int> <dbl> <int> <int>
1 2013 1 1 517 515 2 830 819
2 2013 1 1 533 529 4 850 830
3 2013 1 1 542 540 2 923 850
4 2013 1 1 544 545 -1 1004 1022
5 2013 1 1 554 600 -6 812 837
6 2013 1 1 554 558 -4 740 728
7 2013 1 1 555 600 -5 913 854
8 2013 1 1 557 600 -3 709 723
9 2013 1 1 557 600 -3 838 846
10 2013 1 1 558 600 -2 753 745
# ℹ 336,766 more rows
# ℹ 14 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
# tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
# hour <dbl>, minute <dbl>, time_hour <dttm>, gain <dbl>, hours <dbl>,
# gain_per_hour <dbl>
mutate()
의 범위가 지정된 변형 함수는 여러 변수에 동일한 변형을 적용할 수 있도록 도와줍니다.
mutate_all()
은 모든 변수에 영향을 줍니다.
mutate_at()
은 문자 벡터로 선택한 변수에 영향을 줍니다.
mutate_if()
는 술어 함수(true 또는 false를 반환하는 함수)로 선택한 변수에 영향을 줍니다.
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
# Sepal이라는 문자열을 포함한 모든 열에 log() 함수를 적용해봅시다
mutated <- iris |> mutate_at (vars (contains ("Sepal" )), log)
head (mutated)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 1.629241 1.252763 1.4 0.2 setosa
2 1.589235 1.098612 1.4 0.2 setosa
3 1.547563 1.163151 1.3 0.2 setosa
4 1.526056 1.131402 1.5 0.2 setosa
5 1.609438 1.280934 1.4 0.2 setosa
6 1.686399 1.360977 1.7 0.4 setosa
# 숫자형 변수에만 log()를 적용해봅시다
mutated <- iris |> mutate_if (is.numeric, log)
head (mutated)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 1.629241 1.252763 0.3364722 -1.6094379 setosa
2 1.589235 1.098612 0.3364722 -1.6094379 setosa
3 1.547563 1.163151 0.2623643 -1.6094379 setosa
4 1.526056 1.131402 0.4054651 -1.6094379 setosa
5 1.609438 1.280934 0.3364722 -1.6094379 setosa
6 1.686399 1.360977 0.5306283 -0.9162907 setosa
mutate()
의 범위가 지정된 변형에 대한 자세한 내용은 여기 에서 확인할 수 있습니다.
{tidyverse}
는 빠르게 변화합니다. 패키지(또는 함수)의 라이프사이클을 나타내기 위해 {tidyverse}
는 라이프사이클 배지 를 사용합니다.
이제 across()
는 summarise_at()
, summarise_if()
, summarise_all()
과 같은 “범위가 지정된 변형” 제품군을 대체합니다. 즉, 앞으로 _at()
, _if()
, _all()
함수가 줄어들고 across()
함수가 더 많이 사용될 것입니다.