参考資料


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

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

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

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

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

これから各機能について簡単に解説していく。


実習の準備

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

install.packages("dplyr")
## 
## The downloaded binary packages are in
##  /var/folders/h0/xfy7rcyd2x795bbtrxs0tym40000gn/T//RtmpTDQtv0/downloaded_packages
require(dplyr)
## Loading required package: dplyr

## 
## Attaching package: 'dplyr'

## 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のケースが含まれている。

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

library(nycflights13)

head(flights) # データの中身を見る(最初の6行だけ)
## Source: local data frame [6 x 16]
## 
##    year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##   (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1  2013     1     1      517         2      830        11      UA  N14228
## 2  2013     1     1      533         4      850        20      UA  N24211
## 3  2013     1     1      542         2      923        33      AA  N619AA
## 4  2013     1     1      544        -1     1004       -18      B6  N804JB
## 5  2013     1     1      554        -6      812       -25      DL  N668DN
## 6  2013     1     1      554        -4      740        12      UA  N39463
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

filter()

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

filter(flights, month == 3)
## Source: local data frame [28,834 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     3     1        4       125      318       142      B6  N706JB
## 2   2013     3     1       50        52      526        48      B6  N794JB
## 3   2013     3     1      117       152      223       149      B6  N328JB
## 4   2013     3     1      454        -6      633       -15      US  N177US
## 5   2013     3     1      505       -10      746       -24      UA  N527UA
## 6   2013     3     1      521        -9      813       -14      UA  N76523
## 7   2013     3     1      537        -3      856         6      AA  N5EPAA
## 8   2013     3     1      541        -4     1014        -9      B6  N653JB
## 9   2013     3     1      549       -11      639       -24      US  N749US
## 10  2013     3     1      550       -10      747       -14      EV  N760EV
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

ここで注意すべきなのは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)
## Source: local data frame [908 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     3    10        6         7      336        -2      B6  N547JB
## 2   2013     3    10       41       221      230       213      EV  N14116
## 3   2013     3    10       44        49      416        36      B6  N580JB
## 4   2013     3    10      153       180      302       168      B6  N509JB
## 5   2013     3    10      454        -6      628       -20      US  N125UW
## 6   2013     3    10      512        -3      742       -32      UA  N472UA
## 7   2013     3    10      535        -5      819       -31      AA  N617AA
## 8   2013     3    10      553        -7      815       -15      DL  N643DL
## 9   2013     3    10      555        -5      848       -22      AA  N3CBAA
## 10  2013     3    10      556        -4      801        -4      EV  N398CA
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

filter(flights, month == 3 & (day == 10 | day == 11))
## Source: local data frame [1,888 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     3    10        6         7      336        -2      B6  N547JB
## 2   2013     3    10       41       221      230       213      EV  N14116
## 3   2013     3    10       44        49      416        36      B6  N580JB
## 4   2013     3    10      153       180      302       168      B6  N509JB
## 5   2013     3    10      454        -6      628       -20      US  N125UW
## 6   2013     3    10      512        -3      742       -32      UA  N472UA
## 7   2013     3    10      535        -5      819       -31      AA  N617AA
## 8   2013     3    10      553        -7      815       -15      DL  N643DL
## 9   2013     3    10      555        -5      848       -22      AA  N3CBAA
## 10  2013     3    10      556        -4      801        -4      EV  N398CA
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

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

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

filter(flights, month == 3 & (day == 10 | 11))
## Source: local data frame [28,834 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     3     1        4       125      318       142      B6  N706JB
## 2   2013     3     1       50        52      526        48      B6  N794JB
## 3   2013     3     1      117       152      223       149      B6  N328JB
## 4   2013     3     1      454        -6      633       -15      US  N177US
## 5   2013     3     1      505       -10      746       -24      UA  N527UA
## 6   2013     3     1      521        -9      813       -14      UA  N76523
## 7   2013     3     1      537        -3      856         6      AA  N5EPAA
## 8   2013     3     1      541        -4     1014        -9      B6  N653JB
## 9   2013     3     1      549       -11      639       -24      US  N749US
## 10  2013     3     1      550       -10      747       -14      EV  N760EV
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

filter(flights, month == 3 & (day %in% c(10, 11)))
## Source: local data frame [1,888 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     3    10        6         7      336        -2      B6  N547JB
## 2   2013     3    10       41       221      230       213      EV  N14116
## 3   2013     3    10       44        49      416        36      B6  N580JB
## 4   2013     3    10      153       180      302       168      B6  N509JB
## 5   2013     3    10      454        -6      628       -20      US  N125UW
## 6   2013     3    10      512        -3      742       -32      UA  N472UA
## 7   2013     3    10      535        -5      819       -31      AA  N617AA
## 8   2013     3    10      553        -7      815       -15      DL  N643DL
## 9   2013     3    10      555        -5      848       -22      AA  N3CBAA
## 10  2013     3    10      556        -4      801        -4      EV  N398CA
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

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

実は違う。

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


arrange()

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

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

arrange(flights, month)
## Source: local data frame [336,776 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     1     1      517         2      830        11      UA  N14228
## 2   2013     1     1      533         4      850        20      UA  N24211
## 3   2013     1     1      542         2      923        33      AA  N619AA
## 4   2013     1     1      544        -1     1004       -18      B6  N804JB
## 5   2013     1     1      554        -6      812       -25      DL  N668DN
## 6   2013     1     1      554        -4      740        12      UA  N39463
## 7   2013     1     1      555        -5      913        19      B6  N516JB
## 8   2013     1     1      557        -3      709       -14      EV  N829AS
## 9   2013     1     1      557        -3      838        -8      B6  N593JB
## 10  2013     1     1      558        -2      753         8      AA  N3ALAA
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

arrange(flights, desc(month))
## Source: local data frame [336,776 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013    12     1       13        14      446         1      B6  N715JB
## 2   2013    12     1       17        18      443         6      B6  N593JB
## 3   2013    12     1      453        -7      636       -15      US  N197UW
## 4   2013    12     1      520         5      749       -19      UA  N69804
## 5   2013    12     1      536        -4      845        -5      AA  N634AA
## 6   2013    12     1      540       -10     1005       -22      B6  N821JB
## 7   2013    12     1      541        -4      734       -21      EV  N13968
## 8   2013    12     1      546         1      826        -9      UA  N23708
## 9   2013    12     1      549       -11      648       -11      US  N945UW
## 10  2013    12     1      550       -10      825       -29      B6  N706JB
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

arrange(flights, month, day)
## Source: local data frame [336,776 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013     1     1      517         2      830        11      UA  N14228
## 2   2013     1     1      533         4      850        20      UA  N24211
## 3   2013     1     1      542         2      923        33      AA  N619AA
## 4   2013     1     1      544        -1     1004       -18      B6  N804JB
## 5   2013     1     1      554        -6      812       -25      DL  N668DN
## 6   2013     1     1      554        -4      740        12      UA  N39463
## 7   2013     1     1      555        -5      913        19      B6  N516JB
## 8   2013     1     1      557        -3      709       -14      EV  N829AS
## 9   2013     1     1      557        -3      838        -8      B6  N593JB
## 10  2013     1     1      558        -2      753         8      AA  N3ALAA
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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

arrange(flights, desc(month), desc(day))
## Source: local data frame [336,776 x 16]
## 
##     year month   day dep_time dep_delay arr_time arr_delay carrier tailnum
##    (int) (int) (int)    (int)     (dbl)    (int)     (dbl)   (chr)   (chr)
## 1   2013    12    31       13        14      439         2      B6  N566JB
## 2   2013    12    31       18        19      449         5      DL  N713TW
## 3   2013    12    31       26       101      129        96      B6  N374JB
## 4   2013    12    31      459        -1      655         4      US  N557UW
## 5   2013    12    31      514        -1      814         2      UA  N470UA
## 6   2013    12    31      549        -2      925        25      UA  N577UA
## 7   2013    12    31      550       -10      725       -20      AA  N3CXAA
## 8   2013    12    31      552        -8      811       -15      EV  N14916
## 9   2013    12    31      553        -7      741       -13      DL  N333NB
## 10  2013    12    31      554         4     1024        -3      B6  N552JB
## ..   ...   ...   ...      ...       ...      ...       ...     ...     ...
## Variables not shown: flight (int), origin (chr), dest (chr), air_time
##   (dbl), distance (dbl), hour (dbl), minute (dbl)

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


select()

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

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

select(flights, year, month, day)
## Source: local data frame [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
## ..   ...   ...   ...

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

select(flights, year:day)
## Source: local data frame [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
## ..   ...   ...   ...

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

select(flights, -(year:day))
## Source: local data frame [336,776 x 13]
## 
##    dep_time dep_delay arr_time arr_delay carrier tailnum flight origin
##       (int)     (dbl)    (int)     (dbl)   (chr)   (chr)  (int)  (chr)
## 1       517         2      830        11      UA  N14228   1545    EWR
## 2       533         4      850        20      UA  N24211   1714    LGA
## 3       542         2      923        33      AA  N619AA   1141    JFK
## 4       544        -1     1004       -18      B6  N804JB    725    JFK
## 5       554        -6      812       -25      DL  N668DN    461    LGA
## 6       554        -4      740        12      UA  N39463   1696    EWR
## 7       555        -5      913        19      B6  N516JB    507    EWR
## 8       557        -3      709       -14      EV  N829AS   5708    LGA
## 9       557        -3      838        -8      B6  N593JB     79    JFK
## 10      558        -2      753         8      AA  N3ALAA    301    LGA
## ..      ...       ...      ...       ...     ...     ...    ...    ...
## Variables not shown: dest (chr), air_time (dbl), distance (dbl), hour
##   (dbl), minute (dbl)

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

select(flights, -c(year, month, day))
## Source: local data frame [336,776 x 13]
## 
##    dep_time dep_delay arr_time arr_delay carrier tailnum flight origin
##       (int)     (dbl)    (int)     (dbl)   (chr)   (chr)  (int)  (chr)
## 1       517         2      830        11      UA  N14228   1545    EWR
## 2       533         4      850        20      UA  N24211   1714    LGA
## 3       542         2      923        33      AA  N619AA   1141    JFK
## 4       544        -1     1004       -18      B6  N804JB    725    JFK
## 5       554        -6      812       -25      DL  N668DN    461    LGA
## 6       554        -4      740        12      UA  N39463   1696    EWR
## 7       555        -5      913        19      B6  N516JB    507    EWR
## 8       557        -3      709       -14      EV  N829AS   5708    LGA
## 9       557        -3      838        -8      B6  N593JB     79    JFK
## 10      558        -2      753         8      AA  N3ALAA    301    LGA
## ..      ...       ...      ...       ...     ...     ...    ...    ...
## Variables not shown: dest (chr), air_time (dbl), distance (dbl), hour
##   (dbl), minute (dbl)

これだけでも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"))
## Source: local data frame [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
## ..      ...       ...

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

select(flights, ends_with("time"))
## Source: local data frame [336,776 x 3]
## 
##    dep_time arr_time air_time
##       (int)    (int)    (dbl)
## 1       517      830      227
## 2       533      850      227
## 3       542      923      160
## 4       544     1004      183
## 5       554      812      116
## 6       554      740      150
## 7       555      913      158
## 8       557      709       53
## 9       557      838      140
## 10      558      753      138
## ..      ...      ...      ...

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

select(flights, contains("_"))
## Source: local data frame [336,776 x 5]
## 
##    dep_time dep_delay arr_time arr_delay air_time
##       (int)     (dbl)    (int)     (dbl)    (dbl)
## 1       517         2      830        11      227
## 2       533         4      850        20      227
## 3       542         2      923        33      160
## 4       544        -1     1004       -18      183
## 5       554        -6      812       -25      116
## 6       554        -4      740        12      150
## 7       555        -5      913        19      158
## 8       557        -3      709       -14       53
## 9       557        -3      838        -8      140
## 10      558        -2      753         8      138
## ..      ...       ...      ...       ...      ...

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

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

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

select(flights, 年 = year, 月 = month, 日 = day)
## Source: local data frame [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
## ..   ...   ...   ...

mutate()

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

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

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

flights2 <- select(flights, year:day)
mutate(flights2, doble_year = year * 2)
## Source: local data frame [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
## ..   ...   ...   ...        ...

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

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

mutate(flights2, sum_date = year + month + day)
## Source: local data frame [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
## ..   ...   ...   ...      ...

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

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

mutate(flights2, centered_day = day - mean(day))
## Source: local data frame [336,776 x 4]
## 
##     year month   day centered_day
##    (int) (int) (int)        (dbl)
## 1   2013     1     1    -14.71079
## 2   2013     1     1    -14.71079
## 3   2013     1     1    -14.71079
## 4   2013     1     1    -14.71079
## 5   2013     1     1    -14.71079
## 6   2013     1     1    -14.71079
## 7   2013     1     1    -14.71079
## 8   2013     1     1    -14.71079
## 9   2013     1     1    -14.71079
## 10  2013     1     1    -14.71079
## ..   ...   ...   ...          ...

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))
## Source: local data frame [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))
## Source: local data frame [1 x 2]
## 
##   dep.mean arr.mean
##      (dbl)    (dbl)
## 1  1349.11 1502.055

ちゃんと出来た。

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

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


group_by()と%>%

pipe(%>%)

まずは%>%から紹介する。実はこれは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))
## Source: local data frame [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.183333
## 2   2013     3    18       800      DL   13.333333
## 3   2013     3     8       470      FL    7.833333
## 4   2013     3    18       443      EV    7.383333
## 5   2013     3     8       430      F9    7.166667
## 6   2013     3     8       420      EV    7.000000
## 7   2013     3    24       408      UA    6.800000
## 8   2013     3    14       406      UA    6.766667
## 9   2013     3    12       394      B6    6.566667
## 10  2013     3     8       393      UA    6.550000
## ..   ...   ...   ...       ...     ...         ...

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

flights %>% select(year:day, dep_delay, carrier) %>% 
        filter(month == 3) %>% mutate(sixty_delay = dep_delay / 60) %>%
        arrange(desc(sixty_delay))
## Source: local data frame [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.183333
## 2   2013     3    18       800      DL   13.333333
## 3   2013     3     8       470      FL    7.833333
## 4   2013     3    18       443      EV    7.383333
## 5   2013     3     8       430      F9    7.166667
## 6   2013     3     8       420      EV    7.000000
## 7   2013     3    24       408      UA    6.800000
## 8   2013     3    14       406      UA    6.766667
## 9   2013     3    12       394      B6    6.566667
## 10  2013     3     8       393      UA    6.550000
## ..   ...   ...   ...       ...     ...         ...

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

これまで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))
## Source: local data frame [12 x 2]
## 
##    month mean.delay
##    (int)      (dbl)
## 1      1  10.036665
## 2      2  10.816843
## 3      3  13.227076
## 4      4  13.938038
## 5      5  12.986859
## 6      6  20.846332
## 7      7  21.727787
## 8      8  12.611040
## 9      9   6.722476
## 10    10   6.243988
## 11    11   5.435362
## 12    12  16.576688

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

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

flights %>% group_by(carrier) %>% 
        summarise(mean.delay = mean(dep_delay, na.rm = TRUE)) %>%
        arrange(desc(mean.delay))
## Source: local data frame [16 x 2]
## 
##    carrier mean.delay
##      (chr)      (dbl)
## 1       F9  20.215543
## 2       EV  19.955390
## 3       YV  18.996330
## 4       FL  18.726075
## 5       WN  17.711744
## 6       9E  16.725769
## 7       B6  13.022522
## 8       VX  12.869421
## 9       OO  12.586207
## 10      UA  12.106073
## 11      MQ  10.552041
## 12      DL   9.264505
## 13      AA   8.586016
## 14      AS   5.804775
## 15      HA   4.900585
## 16      US   3.782418

どの会社かは知らんが、F9社の平均延着時間が最も長いらしい。

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

flights %>% group_by(carrier, month) %>%
        summarise(mean.delay = mean(dep_delay, na.rm = TRUE)) %>%
        arrange(desc(mean.delay))
## Source: local data frame [185 x 3]
## Groups: carrier [16]
## 
##    carrier month mean.delay
##      (chr) (int)      (dbl)
## 1       9E     7  31.398827
## 2       9E     6  28.952978
## 3       9E     5  22.672190
## 4       9E    12  19.781088
## 5       9E     8  17.296807
## 6       9E     1  16.882510
## 7       9E     2  16.486327
## 8       9E     4  13.567164
## 9       9E     3  13.407530
## 10      9E    10   9.334348
## ..     ...   ...        ...

もっとも延着時間が長いのは7月の9E社のようだ。


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