dplyrで複数の変数でgroup byしたときは、summariseでグループ化解除されるのはひとつずつ

(タイトルが何言ってるか分からない日本語ですが、メモと言うことで許してください…)

dplyrのvignetteってちゃんと読んだことなかったんですが、訳してみると色々書いてあることに気付きます。

特にこの部分、私は初めて知りました。

When you group by multiple variables, each summary peels off one level of the grouping. That makes it easy to progressively roll-up a dataset:

これがどういうことかというと、たとえば、3つの変数でグループ化したやつがあるとします。

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

これを、一度summarise()すると、一番最後のdayによるグループ化が解除されます。

flights %>%
  group_by(year, month, day) %>%
  summarise(flights = n())
#> Source: local data frame [365 x 4]
#> Groups: year, month [?]
#> 
#>     year month   day flights
#>    (int) (int) (int)   (int)
#> 1   2013     1     1     842
#> 2   2013     1     2     943
#> 3   2013     1     3     914
#> 4   2013     1     4     915
#> ..   ...   ...   ...     ...

もう一度summarise()すると、次のmonthによるグループ化も解除されます。

flights %>%
  group_by(year, month, day) %>%
  summarise(flights = n()) %>%
  summarise(flights = sum(flights))
#> Source: local data frame [12 x 3]
#> Groups: year [?]
#> 
#>     year month flights
#>    (int) (int)   (int)
#> 1   2013     1   27004
#> 2   2013     2   24951
#> 3   2013     3   28834
#> 4   2013     4   28330
#> 5   2013     5   28796
#> 6   2013     6   28243
#> 7   2013     7   29425
#> 8   2013     8   29327
#> 9   2013     9   27574
#> 10  2013    10   28889
#> 11  2013    11   27268
#> 12  2013    12   28135

で、もう一回summarise()すると、完全にグループ化が解除されてただのtbl_dfになります。

flights %>%
  group_by(year, month, day) %>%
  summarise(flights_daily = n()) %>%
  summarise(flights_monthly = sum(flights_daily)) %>%
  summarise(flights_yearly = sum(flights_monthly))
#> Source: local data frame [1 x 2]
#> 
#>    year flights_yearly
#>   (int)          (int)
#> 1  2013         336776

ちなみに、この例は、別々に足し合わせたものを足し合わせても、一気に足し合わせても結果が同じなのでうまくいきますが、平均とか分散とかの場合にはそうはいきません。注意。と書いてありました。

However you need to be careful when progressively rolling up summaries like this: it’s ok for sums and counts, but you need to think about weighting for means and variances (it’s not possible to do this exactly for medians).