/ / dplyr: Jak używać group_by w funkcji? - r, dplyr

dplyr: Jak używać group_by w funkcji? - r, dplyr

Chcę użyć użyj dplyr::group_by funkcja wewnątrz innej funkcji, ale nie wiem, jak przekazać argumenty do tej funkcji.

Czy ktoś może podać przykład pracy?

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

Odpowiedzi:

52 dla odpowiedzi № 1

Do programowania, group_by_ jest odpowiednikiem group_by:

library(dplyr)

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

co daje:

     Species  n
1     setosa 50
2 versicolor 50
3  virginica 50

Aktualizacja W tym czasie został napisany dplyr używany %.% co było pierwotnie używane powyżej, ale teraz %>% jest faworyzowany, więc zmieniliśmy się powyżej, aby zachować tę istotność.

Zaktualizuj 2 regroup jest teraz przestarzałe, użyj zamiast tego group_by_.

Zaktualizuj 3 group_by_(list(...)) teraz staje się group_by_(...) w nowej wersji dplyr zgodnie z komentarzem Roberto.

Aktualizacja 4 Dodano niewielkie zmiany sugerowane w komentarzach.

Aktualizacja 5: Dzięki rlang / tidyeval możliwe jest teraz:

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

lub mijanie Species nienazwany, tzn. bez notowań wokół niego:

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

5 dla odpowiedzi nr 2

AKTUALIZACJA: Od dplyr 0.7.0 możesz użyć porządnego eval, aby to osiągnąć.

Widzieć http://dplyr.tidyverse.org/articles/programming.html po więcej szczegółów.

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 dla odpowiedzi nr 3

Brzydkie, kiedy przychodzą, ale działa:

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

Są prawie na pewno przypadki, które powodują, że to się psuje, ale masz pomysł. Nie wydaje mi się, że możesz sobie poradzić z tym problemem. Jeszcze jedna rzecz, która zadziałała, ale była jeszcze brzydsza:

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