Функция 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)"))
Другие вопросы по тегам