dplyr: ¿Cómo usar group_by dentro de una función?

Deseo utilizar la función dplyr::group_by dentro de otra función, pero no sé cómo pasar los argumentos a esta función.

¿Alguien puede proporcionar un ejemplo de trabajo?

 library(dplyr) data(iris) iris %.% group_by(Species) %.% summarise(n = n()) # ## Source: local data frame [3 x 2] ## Species n ## 1 virginica 50 ## 2 versicolor 50 ## 3 setosa 50 mytable0 <- function(x, ...) x %.% group_by(...) %.% summarise(n = n()) mytable0(iris, "Species") # OK ## Source: local data frame [3 x 2] ## Species n ## 1 virginica 50 ## 2 versicolor 50 ## 3 setosa 50 mytable1 <- function(x, key) x %.% group_by(as.name(key)) %.% summarise(n = n()) mytable1(iris, "Species") # Wrong! # Error: unsupported type for column 'as.name(key)' (SYMSXP) mytable2 <- function(x, key) x %.% group_by(key) %.% summarise(n = n()) mytable2(iris, "Species") # Wrong! # Error: index out of bounds 

Para la progtwigción, group_by_ es la contraparte de group_by :

 library(dplyr) mytable < - function(x, ...) x %>% group_by_(...) %>% summarise(n = n()) mytable(iris, "Species") # or iris %>% mytable("Species") 

lo que da:

  Species n 1 setosa 50 2 versicolor 50 3 virginica 50 

Actualización En el momento en que esto se escribió, dplyr usó %.% Que es lo que se usó originalmente anteriormente, pero ahora se favorece el %>% por lo que se ha cambiado anteriormente para mantenerlo relevante.

El reagrupamiento de la actualización 2 ahora está en desuso, use group_by_ en su lugar.

Actualización 3 group_by_(list(...)) ahora se convierte en group_by_(...) en la nueva versión de dplyr según el comentario de Roberto.

Actualización 4 Se agregó una variación menor sugerida en los comentarios.

Actualización 5: con rlang / tidyeval ahora es posible hacer esto:

 library(rlang) mytable < - function(x, ...) { group_ <- syms(...) x %>% group_by(!!!group_) %>% summarise(n = n()) } mytable(iris, "Species") 

o pasando Species evaluadas, es decir, sin comillas a su alrededor:

 library(rlang) mytable < - function(x, ...) { group_ <- quos(...) x %>% group_by(!!!group_) %>% summarise(n = n()) } mytable(iris, Species) 

ACTUALIZACIÓN : A partir de dplyr 0.7.0 puede usar tidy eval para lograr esto.

Ver http://dplyr.tidyverse.org/articles/programming.html para más detalles.

 library(tidyverse) data("iris") my_table < - function(df, group_var) { group_var <- enquo(group_var) # Create quosure df %>% group_by(!!group_var) %>% # Use !! to unquote the quosure summarise(n = n()) } my_table(iris, Species) > my_table(iris, Species) # A tibble: 3 x 2 Species n   1 setosa 50 2 versicolor 50 3 virginica 50 

Feo como vienen, pero ella trabaja:

 mytable3 < - function(x, key) { my.call <- bquote(summarise(group_by(.(substitute(x)), NULL), n = n())) my.call[[2]][[3]] <- as.name(key) eval(my.call, parent.frame()) } mytable3(iris, "Species") # Source: local data frame [3 x 2] # # Species n # 1 virginica 50 # 2 versicolor 50 # 3 setosa 50 

Es casi seguro que habrá casos que harán que esto se rompa, pero se entiende la idea. No creo que puedas evitar la llamada. Otra cosa que sí funcionó pero que fue aún más fea es:

 mytable4 < - function(x, key) summarise(group_by(x, x[[key]]), n = n())