dplyr入門 (旧版)

統計学 R データハンドリング

参考資料


dplyrはR業界の神様、Hadley Wickhamが作成したRのパッケージである。 R内蔵の関数でもデータの管理はできるが、dplyrを使うと生産性は何倍も向上する。

dplyrの主な使い道は以下のとおり

関数名 機能
filter ある条件に合ったケースだけを抽出
arrange データをある基準に合わせて揃える
select 指定した変数のみを抽出
mutate 計算した結果を新しい変数として定義
summarise データの要約

これらの機能を最大限発揮するために、いくつかの良き友達がいる

関数名 機能
group_by データのグループ化
%>% (注) 複数の処理を逐次的に実行

※なぜか2行目は%>%と表示されていますが、正しいのは%>%です。


実習の準備

まずは、dplyrのインストールと読み込みである。dplyrはCRANに登録されているので、install.packages()でインストールできる。

install.packages("dplyr")
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

実習用データは有名なnycflights13データを使う。これはニューヨーク出発の航空便のデータで、336,776のケースが含まれている。インストールされていない場合、install.packages("nycflights13")でインストールしておこう。

まず、データを読み込み、中身を見てみよう。

library(nycflights13)

head(flights) # データの中身を見る(最初の6行だけ)
## # A tibble: 6 x 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
## # … with 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>

filter()

filter()はある条件に合ったケースのみを抽出する関数である。使い方はfilter(データ, 条件)である。ここでデータはflightsである。試しに3月のデータだけを抽出してみる。月はmonth変数である。

filter(flights, month == 3)
## # A tibble: 28,834 x 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     3     1        4           2159       125      318             56
##  2  2013     3     1       50           2358        52      526            438
##  3  2013     3     1      117           2245       152      223           2354
##  4  2013     3     1      454            500        -6      633            648
##  5  2013     3     1      505            515       -10      746            810
##  6  2013     3     1      521            530        -9      813            827
##  7  2013     3     1      537            540        -3      856            850
##  8  2013     3     1      541            545        -4     1014           1023
##  9  2013     3     1      549            600       -11      639            703
## 10  2013     3     1      550            600       -10      747            801
## # … with 28,824 more rows, and 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>

ここで注意すべきなのはmonth = 3ではなく、month == 3ということだ。 ほとんどの言語で=は代入を意味する。「同じ」を意味するわけではない。

簡単にまとめてみよう

演算子 意味
A == B AとBは同値
A < B AはBより小さい(未満)
A > B AはBより大きい(超過)
A <= B AはBより小さいか、同じ(以下)
A >= B AはBより大きいか、同じ(以上)
A != B AとBは同じではない

先ほどの例では3月(month == 3)のデータを抽出したが、もっと条件を絞ることもできる。

たとえば、3月10日に絞りたい場合の条件式はmonth == 3 & day == 10である。

filter(flights, month == 3 & day == 10)
## # A tibble: 908 x 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     3    10        6           2359         7      336            338
##  2  2013     3    10       41           2100       221      230           2257
##  3  2013     3    10       44           2355        49      416            340
##  4  2013     3    10      153           2253       180      302             14
##  5  2013     3    10      454            500        -6      628            648
##  6  2013     3    10      512            515        -3      742            814
##  7  2013     3    10      535            540        -5      819            850
##  8  2013     3    10      553            600        -7      815            830
##  9  2013     3    10      555            600        -5      848            910
## 10  2013     3    10      556            600        -4      801            805
## # … with 898 more rows, and 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>

&はANDを意味する。もし、3月10日と11日のデータがほしいなるどうすればいいか。 この場合、OR表現が必要となる。ORは|と書く。

filter(flights, month == 3 & (day == 10 | day == 11))
## # A tibble: 1,888 x 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     3    10        6           2359         7      336            338
##  2  2013     3    10       41           2100       221      230           2257
##  3  2013     3    10       44           2355        49      416            340
##  4  2013     3    10      153           2253       180      302             14
##  5  2013     3    10      454            500        -6      628            648
##  6  2013     3    10      512            515        -3      742            814
##  7  2013     3    10      535            540        -5      819            850
##  8  2013     3    10      553            600        -7      815            830
##  9  2013     3    10      555            600        -5      848            910
## 10  2013     3    10      556            600        -4      801            805
## # … with 1,878 more rows, and 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>

ここで条件式はANDとORの組み合わせになっている。簡単に表現すると「A and (B or C)」である。これは

  • (AかつB) あるいは(AかつC)

を意味する。ちなみに以上のコマンドはもっと省略できる。

filter(flights, month == 3 & (day == 10 | 11))
## # A tibble: 28,834 x 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     3     1        4           2159       125      318             56
##  2  2013     3     1       50           2358        52      526            438
##  3  2013     3     1      117           2245       152      223           2354
##  4  2013     3     1      454            500        -6      633            648
##  5  2013     3     1      505            515       -10      746            810
##  6  2013     3     1      521            530        -9      813            827
##  7  2013     3     1      537            540        -3      856            850
##  8  2013     3     1      541            545        -4     1014           1023
##  9  2013     3     1      549            600       -11      639            703
## 10  2013     3     1      550            600       -10      747            801
## # … with 28,824 more rows, and 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>

day ==を一回書くだけでも結果は同じ。ちなみに、OR演算の他の表現法もある。それは%in%である。 A %in% (1, 2, 3, 4)は「Aが1, 2, 3, 4どっちかに該当するか」を意味する。これを使って先のコマンドを書きなおしてみよう。

filter(flights, month == 3 & (day %in% c(10, 11)))
## # A tibble: 1,888 x 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     3    10        6           2359         7      336            338
##  2  2013     3    10       41           2100       221      230           2257
##  3  2013     3    10       44           2355        49      416            340
##  4  2013     3    10      153           2253       180      302             14
##  5  2013     3    10      454            500        -6      628            648
##  6  2013     3    10      512            515        -3      742            814
##  7  2013     3    10      535            540        -5      819            850
##  8  2013     3    10      553            600        -7      815            830
##  9  2013     3    10      555            600        -5      848            910
## 10  2013     3    10      556            600        -4      801            805
## # … with 1,878 more rows, and 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>

やはり結果は変わらない。ちなみに、Rで複数の要素(数字でも文字でも)を並ぶときにはc()を使う。ただし、一つのベクトルに数字が文字が混在されることはない。

このデータを使っては実習できないが、欠損値のあるケースを除去したい場合もあろう。 たとえば、yearが欠損値になってるケースが除去したいならfilter(flights, year == NA)で良いだろうか。

実は違う。

この場合はis.na(year)と書く。理由は聞かないでほしい。


arrange()

arrangeはケースをある基準に合わせて並べ直す関数である。

特に意味はないが、データをmonthが小さい順に並べてみよう。

arrange(flights, month)
## # A tibble: 336,776 x 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
## # … with 336,766 more rows, and 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>

もし、大きい方から表示したいならdesc()を使う。

arrange(flights, desc(month))
## # A tibble: 336,776 x 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    12     1       13           2359        14      446            445
##  2  2013    12     1       17           2359        18      443            437
##  3  2013    12     1      453            500        -7      636            651
##  4  2013    12     1      520            515         5      749            808
##  5  2013    12     1      536            540        -4      845            850
##  6  2013    12     1      540            550       -10     1005           1027
##  7  2013    12     1      541            545        -4      734            755
##  8  2013    12     1      546            545         1      826            835
##  9  2013    12     1      549            600       -11      648            659
## 10  2013    12     1      550            600       -10      825            854
## # … with 336,766 more rows, and 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>

次は「monthの順で並べて、もし同じなら、次はdayの順で並べたい」である。どうすればいいだろうか。実はこれも簡単だ。 条件式に次の基準となる変数名を入れるだけでいい。

arrange(flights, month, day)
## # A tibble: 336,776 x 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
## # … with 336,766 more rows, and 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>

これを「monthは12から1へ、dayも31から1の順で並べたい」と思うなら

arrange(flights, desc(month), desc(day))
## # A tibble: 336,776 x 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    12    31       13           2359        14      439            437
##  2  2013    12    31       18           2359        19      449            444
##  3  2013    12    31       26           2245       101      129           2353
##  4  2013    12    31      459            500        -1      655            651
##  5  2013    12    31      514            515        -1      814            812
##  6  2013    12    31      549            551        -2      925            900
##  7  2013    12    31      550            600       -10      725            745
##  8  2013    12    31      552            600        -8      811            826
##  9  2013    12    31      553            600        -7      741            754
## 10  2013    12    31      554            550         4     1024           1027
## # … with 336,766 more rows, and 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>

最後に、欠損値(NA)は常に一番最後の行になる。


select()

これは指定した変数のみを抽出する関数である。

まず、year, month, day列のみを抽出してみよう。

select(flights, year, month, day)
## # A tibble: 336,776 x 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
## # … with 336,766 more rows

このように隣接している変数同士なら:が使える。year:dayは「yearからdayまで」という意味だ。

select(flights, year:day)
## # A tibble: 336,776 x 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
## # … with 336,766 more rows

yearからdayまで表示するのではなくyearからdayまでを表示させないこともできる。その時に使うのが-である。

select(flights, -(year:day))
## # A tibble: 336,776 x 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     
## # … with 336,766 more rows, and 9 more variables: flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

-year:dayでなく、-(year:day)であることに注意しよう。もし:を使わないなら-c(year, month, day)のように書く。

select(flights, -c(year, month, day))
## # A tibble: 336,776 x 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     
## # … with 336,766 more rows, and 9 more variables: flight <int>, tailnum <chr>,
## #   origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>, hour <dbl>,
## #   minute <dbl>, time_hour <dttm>

これだけでもselect()は大変便利な関数だが、もっと高度な使い方もある。

まずは、そのリストから

演算子 意味
starts_with("ABC") 変数名がABCで始まる変数
ends_with("XYZ") 変数名がXYZで終わる変数
contains("LMN") 変数名にLMNが含まれている変数
matches("(.)\\1") 正規表現パターン
num_range("X", 1:3) X1, X2, X3

まずは、変数名がdepで始まる変数のみを抽出してみる。

select(flights, starts_with("dep"))
## # A tibble: 336,776 x 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
## # … with 336,766 more rows

続いて、変数名がtimeで終わるやつ

select(flights, ends_with("time"))
## # A tibble: 336,776 x 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
## # … with 336,766 more rows

最後に_(アンダーバー)が含まれているやつ

select(flights, contains("_"))
## # A tibble: 336,776 x 8
##    dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay air_time
##       <int>          <int>     <dbl>    <int>          <int>     <dbl>    <dbl>
##  1      517            515         2      830            819        11      227
##  2      533            529         4      850            830        20      227
##  3      542            540         2      923            850        33      160
##  4      544            545        -1     1004           1022       -18      183
##  5      554            600        -6      812            837       -25      116
##  6      554            558        -4      740            728        12      150
##  7      555            600        -5      913            854        19      158
##  8      557            600        -3      709            723       -14       53
##  9      557            600        -3      838            846        -8      140
## 10      558            600        -2      753            745         8      138
## # … with 336,766 more rows, and 1 more variable: time_hour <dttm>

matchesに関しては私も詳しくない。正規表現を使う時はいつもネットを参照しているので…

num_rangeはこのデータでは使えないがselect(data, num_range("X", 3:5))と書いたら、dataというデータからX3, X4, X5のみを抽出せよという意味である。

個人的にあまり使わない機能だが、抽出後、新しい名前を付けることもできる。

select(flights, 年 = year, 月 = month, 日 = day)
## # A tibble: 336,776 x 3
##       年    月    日
##    <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
## # … with 336,766 more rows

mutate()

mutateはデータを計算し、その結果を新しい変数として格納する関数である。

使い方はmutate(データ, 新しい変数名 = 計算式)である。

とくに意味はないが、年(year)を2倍にし、double_yearという変数として表示させてみよう。 (変数が多すぎて画面上に表示されないので、yearからdayまで抽出したデータ(flights2)を使う。)

flights2 <- select(flights, year:day)
mutate(flights2, doble_year = year * 2)
## # A tibble: 336,776 x 4
##     year month   day doble_year
##    <int> <int> <int>      <dbl>
##  1  2013     1     1       4026
##  2  2013     1     1       4026
##  3  2013     1     1       4026
##  4  2013     1     1       4026
##  5  2013     1     1       4026
##  6  2013     1     1       4026
##  7  2013     1     1       4026
##  8  2013     1     1       4026
##  9  2013     1     1       4026
## 10  2013     1     1       4026
## # … with 336,766 more rows

ちゃんとdouble_yearという列さ生成されて、yearの2倍になっていることが分かる。

次はyearmonthdayを全部足し、sum_dataと名付けよう。

mutate(flights2, sum_date = year + month + day)
## # A tibble: 336,776 x 4
##     year month   day sum_date
##    <int> <int> <int>    <int>
##  1  2013     1     1     2015
##  2  2013     1     1     2015
##  3  2013     1     1     2015
##  4  2013     1     1     2015
##  5  2013     1     1     2015
##  6  2013     1     1     2015
##  7  2013     1     1     2015
##  8  2013     1     1     2015
##  9  2013     1     1     2015
## 10  2013     1     1     2015
## # … with 336,766 more rows

これ以外にもcumsumlogなどの関数を使うこともできるし、平均値を引くことも出来る。

例としてdayからdayの平均値を引いた値をcentered_dayとして表示させてみる。

mutate(flights2, centered_day = day - mean(day))
## # A tibble: 336,776 x 4
##     year month   day centered_day
##    <int> <int> <int>        <dbl>
##  1  2013     1     1        -14.7
##  2  2013     1     1        -14.7
##  3  2013     1     1        -14.7
##  4  2013     1     1        -14.7
##  5  2013     1     1        -14.7
##  6  2013     1     1        -14.7
##  7  2013     1     1        -14.7
##  8  2013     1     1        -14.7
##  9  2013     1     1        -14.7
## 10  2013     1     1        -14.7
## # … with 336,766 more rows

summarise()

summariseは変数の平均、中央値、標準偏差などの統計量を表示させる関数である。

使い方はsummarise(データ, 新しい変数名 = 関数(変数))である。

ここではflightデータに戻ってdep_timearr_timeの平均値を見てみたい。 dep_timeの平均値はdep.meanarr_timeの平均値はarr.meanとしよう。

summarise(flights, dep.mean = mean(dep_time), arr.mean = mean(arr_time))
## # A tibble: 1 x 2
##   dep.mean arr.mean
##      <dbl>    <dbl>
## 1       NA       NA

mean()関数は欠損値が含まれているとNAを返すので、これを無視するように引数としてna.rm = TRUEを付ける。

summarise(flights, 
          dep.mean = mean(dep_time, na.rm = TRUE), 
          arr.mean = mean(arr_time, na.rm = TRUE))
## # A tibble: 1 x 2
##   dep.mean arr.mean
##      <dbl>    <dbl>
## 1    1349.    1502.

ちゃんと出来た。

ここでのmean()以外に標準偏差(sd())、IQR(IQR())、中央値(median())なども使える。 また、よく使われるものとしてケース数(n())がある。

summarise関数はこれから紹介するgroup_byと一緒に使う時が多い。


group_by()と%>%

pipeline (%>%)

まずは%>%から紹介する。実はこれはdplyr独特のものではないが、dplyrとの相性がいい。

先ほど、flightsの変数が多すぎてyear:dayのみ抽出し、mutateを使ったの例を考えてみる。 まずはflights2を作って、そこからmutateをした。まぁ、二行で終わったし、そこまで面倒くさくはないかも知れない。

それでは次の例を考えてみよう。

  1. year, month, day, dep_delay, carrierを抽出
  2. 3月のデータのみ抽出
  3. dep_delayを60で割って、sixty_delayと名付ける。
  4. sixty_delayが大きい順に並べ替える。

これをこれまでの方式でやってみよう。

temp.flights <- select(flights, year:day, dep_delay, carrier)
temp.flights <- filter(temp.flights, month == 3)
temp.flights <- mutate(temp.flights, sixty_delay = dep_delay / 60)
arrange(temp.flights, desc(sixty_delay))
## # A tibble: 28,834 x 6
##     year month   day dep_delay carrier sixty_delay
##    <int> <int> <int>     <dbl> <chr>         <dbl>
##  1  2013     3    17       911 DL            15.2 
##  2  2013     3    18       800 DL            13.3 
##  3  2013     3     8       470 FL             7.83
##  4  2013     3    18       443 EV             7.38
##  5  2013     3     8       430 F9             7.17
##  6  2013     3     8       420 EV             7   
##  7  2013     3    24       408 UA             6.8 
##  8  2013     3    14       406 UA             6.77
##  9  2013     3    12       394 B6             6.57
## 10  2013     3     8       393 UA             6.55
## # … with 28,824 more rows

これを%>%を使って短めにする。

flights %>% 
    select(year:day, dep_delay, carrier) %>% 
    filter(month == 3) %>% 
    mutate(sixty_delay = dep_delay / 60) %>%
    arrange(desc(sixty_delay))
## # A tibble: 28,834 x 6
##     year month   day dep_delay carrier sixty_delay
##    <int> <int> <int>     <dbl> <chr>         <dbl>
##  1  2013     3    17       911 DL            15.2 
##  2  2013     3    18       800 DL            13.3 
##  3  2013     3     8       470 FL             7.83
##  4  2013     3    18       443 EV             7.38
##  5  2013     3     8       430 F9             7.17
##  6  2013     3     8       420 EV             7   
##  7  2013     3    24       408 UA             6.8 
##  8  2013     3    14       406 UA             6.77
##  9  2013     3    12       394 B6             6.57
## 10  2013     3     8       393 UA             6.55
## # … with 28,824 more rows

まったく同じ結果が得られた。

これまでselect()filter()などの関数の最初の引数はデータ名だったが、それも要らなくなった。

flights %>%は「次に処理するデータはflightsです」という意味だ。この例ではflightsデータを使ってselect()をした。

select()で絞られたデータはそのまま次のfilter()のデータとして使われる。

こんな感じでデータが次々へと伝達されていくのが%>%の素晴らしいところだ。


group_by()

では、最後にgroup_by()を見てみよう。

これはある変数(ほとんどカテゴリカル変数)でデータをグループ化するものである。

たとえば各月の平均延着時間の見たいとする。

  • flights %>% filter(month == 1) %>% summarise(mean.delay = mean(dep_delay))
  • flights %>% filter(month == 2) %>% summarise(mean.delay = mean(dep_delay))
  • flights %>% filter(month == 12) %>% summarise(mean.delay = mean(dep_delay))

のように12回やってもいいが、monthを基準にグループ化すると一瞬で終わる。

flights %>% 
    group_by(month) %>% 
    summarise(mean.delay = mean(dep_delay, na.rm = TRUE))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 12 x 2
##    month mean.delay
##    <int>      <dbl>
##  1     1      10.0 
##  2     2      10.8 
##  3     3      13.2 
##  4     4      13.9 
##  5     5      13.0 
##  6     6      20.8 
##  7     7      21.7 
##  8     8      12.6 
##  9     9       6.72
## 10    10       6.24
## 11    11       5.44
## 12    12      16.6

これはflightsデータをmonthを基準にグループ化し、それぞれsummarise()した結果を表示する仕組みである。

航空会社(carrier)ごとに見てみよう。

flights %>% 
    group_by(carrier) %>% 
    summarise(mean.delay = mean(dep_delay, na.rm = TRUE)) %>%
    arrange(desc(mean.delay))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 16 x 2
##    carrier mean.delay
##    <chr>        <dbl>
##  1 F9           20.2 
##  2 EV           20.0 
##  3 YV           19.0 
##  4 FL           18.7 
##  5 WN           17.7 
##  6 9E           16.7 
##  7 B6           13.0 
##  8 VX           12.9 
##  9 OO           12.6 
## 10 UA           12.1 
## 11 MQ           10.6 
## 12 DL            9.26
## 13 AA            8.59
## 14 AS            5.80
## 15 HA            4.90
## 16 US            3.78

F9社 (アメリカのFrontier Airlinesらしい)の平均延着時間が最も長いらしい。

グループは一つの変数でなく、複数の変数を指定することもできる。各航空会社の月別平均延着時間は

flights %>% 
    group_by(carrier, month) %>%
    summarise(mean.delay = mean(dep_delay, na.rm = TRUE)) %>%
    arrange(desc(mean.delay))
## `summarise()` regrouping output by 'carrier' (override with `.groups` argument)
## # A tibble: 185 x 3
## # Groups:   carrier [16]
##    carrier month mean.delay
##    <chr>   <int>      <dbl>
##  1 OO          1       67  
##  2 OO          8       64  
##  3 OO          6       61  
##  4 HA          1       54.4
##  5 YV          6       42.8
##  6 FL          7       41.2
##  7 FL          6       38.8
##  8 F9          5       35.9
##  9 VX          7       35.3
## 10 YV          3       31.9
## # … with 175 more rows

もっとも延着時間が長いのは7月の9E社 (アメリカのEndeavor Air)のようだ。


大雑把にdplyrの機能を紹介したが、ここで紹介したよりも多くの機能があり、その便利さは我らの想像を超えるほどだ。 興味のある人はDatacampとか、他のチュートリアルを見てみるのもいいと思う。