将多个调用参数传递给dplyr自定义函数中的形式参数,而无需使用"..."; [英] Pass multiple calling arguments to a formal argument in dplyr custom function without using "..."

查看:99
本文介绍了将多个调用参数传递给dplyr自定义函数中的形式参数,而无需使用"...";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要使自定义函数灵活地接收每个形式参数中的一个或多个调用参数,我目前依靠"...":

To make a custom function flexible to receiving one or more calling arguments per formal argument I currently rely on "...":

library(dplyr)

foo <- function(data, ..., dv){
  groups <- enquos(...)
  dv <- enquo(dv)
  data %>% 
    group_by(!!!groups) %>% 
    summarise(group_mean = mean(!!dv))
}

mtcars %>% foo(am, dv = mpg)
mtcars %>% foo(vs, am, dv = mpg)

但是"..."掩盖了函数的逻辑,并且不能在具有2个或更多个需要多个调用参数的形式参数的自定义函数中使用.

But "..." obscures the logic of the function, and it could not be used in a custom function with 2 or more formal arguments requiring multiple calling arguments.

有没有一种方法可以编写上述函数来利用形式参数(例如组")而不是"...",后者可以接收单个向量名称或向量名称向量作为其参数?像这样:

Is there a way to write the above function to utilize a formal argument (e.g., "groups") rather than "..." that can receive a single vector name or a vector of vector names as its argument(s)? Something like:

foo <- function(data, groups, dv){
  groups <- enquos(groups)
  dv <- enquo(dv)

  data %>% 
    group_by(!!!groups) %>% 
    summarise(group_mean = mean(!!dv))
}

# Failing code
mtcars %>% foo(groups = c(vs, am), dv = mpg)

请注意,此代码可以工作,但要求用户记住在函数体中使用quos():

Note that this code would work, but require user to remember to use quos() in function body:

foo <- function(data, groups, dv){
  dv <- enquo(dv)

  data %>% 
    group_by(!!!groups) %>% 
    summarise(group_mean = mean(!!dv))
}

mtcars %>% foo(groups = quos(vs, am), dv = mpg)

我希望改为依靠函数体中的enquos().

I'd love to rely on enquos() in body of function instead.

推荐答案

我们可以将...放在最后

foo <- function(data,  dv, ...){
   groups <- enquos(...)
   dv <- enquo(dv)
   data %>% 
     group_by(!!!groups) %>% 
     summarise(group_mean = mean(!!dv))
  }


如果我们要传递'group'的vector,则一个选项是group_by_at


If we want to pass a vector of 'group', then one option is group_by_at

foo <- function(data, groups, dv){
  dv <- enquo(dv)

  data %>% 
     group_by_at(vars(groups)) %>% 
     summarise(group_mean = mean(!!dv))
  }

mtcars %>% 
    foo(groups = c("vs", "am"), dv = mpg)
# A tibble: 4 x 3
# Groups:   vs [?]
#     vs    am group_mean
#  <dbl> <dbl>      <dbl>
#1     0     0       15.0
#2     0     1       19.8
#3     1     0       20.7
#4     1     1       28.4


如果我们想用c传递不带引号的表达式,一种选择是将其转换为表达式然后对其求值


One option if we want to pass unquoted expression with c would be to convert it to expression and then evaluate it

foo <- function(data, groups, dv){

 groups <- as.list(rlang::enexpr(groups))[-1]
 dv <- enquo(dv)
   data %>% 
      group_by(!!! groups) %>% 
      summarise(group_mean = mean(!!dv))
 }

mtcars %>% 
      foo(groups = c(vs, am), dv = mpg)
# A tibble: 4 x 3
# Groups:   vs [?]
#     vs    am group_mean
#  <dbl> <dbl>      <dbl>
#1     0     0       15.0
#2     0     1       19.8
#3     1     0       20.7
#4     1     1       28.4

或者如评论中提到的@Joe一样,enquo也应与group_by_at

Or as @Joe mentioned in the comments, enquo should also work with group_by_at

foo <- function(data, groups, dv){
   dv <- enquo(dv) 
   groups <- enquos(groups) 
   data %>% 
        group_by_at(vars(!!!groups)) %>% 
        summarise(group_mean = mean(!!dv))
   } 

mtcars %>% 
     foo(groups = c(vs, am), dv = mpg)
# A tibble: 4 x 3
# Groups:   vs [?]
#     vs    am group_mean
#  <dbl> <dbl>      <dbl>
#1     0     0       15.0
#2     0     1       19.8
#3     1     0       20.7
#4     1     1       28.4

这篇关于将多个调用参数传递给dplyr自定义函数中的形式参数,而无需使用"...";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆