dplyr: by + do.call("rbind")するならdoすべし
"グループ毎にXXXしたい"という時のXXXの内容が複雑な場合、関数として処理を切り出したくて、以下のように書いてみた。
処理の内容は"Speciesのグループ毎にその最終行のPetal.Lengthの値を取得する"だ。
> process <- function(df){ + df[nrow(df),]$Petal.Length + } > iris %>% + group_by(Species) %>% + summarize(result = process(.)) Source: local data frame [3 x 2] Species result (fctr) (dbl) 1 setosa 5.1 2 versicolor 5.1 3 virginica 5.1
・・・が、この結果は間違いで正しくは以下のようにdo関数をかませて処理を書かねばならない(adviced by hoxo_m)。
iris %>% group_by(Species) %>% do(result = process(.)) %>% summarize(Species, result)
これはbaseの関数を使っても一応かけて、以下の結果と等価だが、明らかに上の書き方の方が筋が良い。したがって
- by + do.call("rbind") = do
として覚えることにする。
> iris %>% + by(iris$Species, FUN=function(df){ + group <- head(df$Species, 1) + data.frame(group, value=df[nrow(df),]$Petal.Length) + }) %>% do.call("rbind", .) group value setosa setosa 1.4 versicolor versicolor 4.1 virginica virginica 5.1
結局do関数とは?
HELPを見ても意味が分からなかったので、例で覚える。要するに
- 各グループに対するめんどくさ系な処理(単一の列ではなく、data.frame全体を使ってやる処理など)を書く
という印象だ。
> by_cyl <- group_by(mtcars, cyl) > do(by_cyl, head(., 2)) Source: local data frame [6 x 11] Groups: cyl [3] mpg cyl disp hp drat wt qsec vs am gear carb (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) 1 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 2 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 3 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 4 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 6 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 > group_by(mtcars, cyl) %>% summarize(n()) Source: local data frame [3 x 2] cyl n() (dbl) (int) 1 4 11 2 6 7 3 8 14