Функция R с выражением в качестве параметра для суммирования dplyr
Хорошо, это то, что должно быть относительно легко, но хотя я пробовал буквально десятки подходов с quote
, eval
, substitute
, enquote
, parse
, summarize_
и т.д... Я не получил его на работу. В основном я пытаюсь вычислить что-то вроде этого - но с переменным выражением для summarise
аргумент:
mtcars %>% group_by(cyl) %>% summarise(wt=mean(wt),hp=mean(hp))
получая:
# A tibble: 3 × 3
cyl wt hp
<dbl> <dbl> <dbl>
1 4 2.285727 82.63636
2 6 3.117143 122.28571
3 8 3.999214 209.21429
Одна из вещей, которые я попробовал, была:
x2 <- "wt=mean(wt),hp=mean(hp)"
mtcars %>% group_by(cyl) %>% summarise(eval(parse(text=x2)))
получая:
Error in eval(substitute(expr), envir, enclos) :
<text>:1:12: unexpected ','
1: wt=mean(wt),
Но оставив второй аргумент (",hp=mean(hp"
) не дает вам дальше:
> x2 <- "wt=mean(wt)"
> mtcars %>% group_by(cyl) %>% summarise(eval(parse(text=x2)))
Error in eval(substitute(expr), envir, enclos) : object 'wt' not found
Я избавлю вас от всего остального, что я пробовал - мне явно не хватает того, как выражения обрабатываются в аргументах функции.
Так каков здесь правильный подход? Имея в виду, я действительно хочу что-то вроде этого в конце:
getdf <- function(df,sumarg){
df %>% group_by(cyl) %>% summarise(sumarg)
df
}
Также не уверен, какой тег я должен использовать для такого рода запросов в мире R. Метапрограммирование?
1 ответ
Для максимальной гибкости я бы использовал ...
аргумент, захватить эти точки использовать lazyeval
, а затем перейти к summarise_
:
getdf <- function(df, ...){
df %>% group_by(cyl) %>% summarise_(.dots = lazyeval::lazy_dots(...))
}
Тогда вы можете напрямую сделать:
getdf(mtcars, wt = mean(wt), hp = mean(hp))
# A tibble: 3 × 3 cyl wt hp <dbl> <dbl> <dbl> 1 4 2.285727 82.63636 2 6 3.117143 122.28571 3 8 3.999214 209.21429
Один из способов сделать это без ...
, это передать аргументы в списке, хотя вам нужно будет использовать формулы или кавычки. Например:
getdf2 <- function(df, args){
dots <- lazyeval::as.lazy_dots(args)
df %>% group_by(cyl) %>% summarise_(.dots = dots)
}
И использовать как:
getdf(mtcars, list(wt = ~mean(wt), hp = ~mean(hp)))
или же
getdf(mtcars, list(wt = "mean(wt)", hp = "mean(hp)"))