/ / dplyr: come usare group_by all'interno di una funzione? - r, dplyr

dplyr: Come usare group_by all'interno di una funzione? - r, dplyr

Voglio usare usare il dplyr::group_by funzione all'interno di un'altra funzione, ma non so come passare gli argomenti a questa funzione.

Qualcuno può fornire un esempio funzionante?

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

risposte:

52 per risposta № 1

Per la programmazione, group_by_ è la controparte di group_by:

library(dplyr)

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

che dà:

     Species  n
1     setosa 50
2 versicolor 50
3  virginica 50

Aggiornare Al momento questo è stato scritto dplyr usato %.% che è ciò che era originariamente usato sopra ma ora %>% è favorito, quindi sono cambiati in precedenza per tenerlo presente.

Aggiornamento 2 il gruppo è ora deprecato, usa invece group_by_.

Aggiornamento 3 group_by_(list(...)) ora diventa group_by_(...) nella nuova versione di dplyr come da commento di Roberto.

Aggiornamento 4 Aggiunta variazione minore suggerita nei commenti.

Aggiornamento 5: Con rlang / tidyeval ora è possibile farlo:

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

o passando Species non valutato, cioè senza virgolette intorno:

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

5 per risposta № 2

AGGIORNARE: A partire da dplyr 0.7.0 puoi usare eval ordinato per realizzare questo.

Vedere http://dplyr.tidyverse.org/articles/programming.html per ulteriori dettagli.

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
<fctr> <int>
1     setosa    50
2 versicolor    50
3  virginica    50

2 per risposta № 3

Brutti come vengono, ma lei lavora:

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

Ci sono quasi certamente casi che causeranno la rottura di questo, ma tu hai l'idea. Non penso che tu possa andare in giro con la chiamata, un'altra cosa che ha funzionato ma che è stata ancora più brutta è:

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