R 中 rlang::enexpr() 中的行为 as.list

Behavior as.list in rlang::enexpr() in R

我试着想有什么方法可以为每个参数设置多个变量。如果我使用 ensyms,我不能像我在函数中提供的那样拥有一个向量,但我希望该函数同时适用于 groups = c(am, vs)groups = c("am", "vs")

如果我使用 groups = c("am", "vs"),前 2 列会多出 2 列,如果我使用 groups = c(am, vs),则后两列可以正常工作。我使用 select_vars = c( "mpg","disp")select_vars = c( mpg, disp)

selected_var 工作正常

有什么想法可以帮助吗?

tryfn <- function(data, select_vars,groups, ...){
  
  select_vars <- as.list(rlang::enexpr(select_vars ))
  select_vars <- if(length(select_vars) > 1) select_vars[-1] else select_vars
  
  group_vars <- as.list(rlang::enexpr(groups))
  group_vars  <- if(length(group_vars ) > 1) group_vars[-1] else group_vars 

  data %>% select(!!!group_vars,!!!select_vars) %>% group_by(!!!group_vars)
 
  
}

# If I used groups argument as string, it gave me 2 extra columns 

tryfn(mtcars, select_vars = c( "mpg","disp"), groups = c("am", "vs"))
tryfn(mtcars, select_vars = c( mpg, disp), groups = c("am", "vs"))

> tryfn(mtcars, select_vars = c( mpg, disp), groups = c("am", "vs"))
# A tibble: 32 x 6
# Groups:   "am", "vs" [1]
      am    vs   mpg  disp **`"am"` `"vs"`**
   <dbl> <dbl> <dbl> <dbl> <chr>  <chr> 
 1     1     0  21    160  am     vs    
 2     1     0  21    160  am     vs    
 3     1     1  22.8  108  am     vs    
 4     0     1  21.4  258  am     vs    
 5     0     0  18.7  360  am     vs    
 6     0     1  18.1  225  am     vs    
 7     0     0  14.3  360  am     vs    
 8     0     1  24.4  147. am     vs    
 9     0     1  22.8  141. am     vs    
10     0     1  19.2  168. am     vs    

# this one is working perfectly
tryfn(mtcars, select_vars = c( mpg, disp), groups = c(am, vs))
tryfn(mtcars, select_vars = c( "mpg","disp"), groups = c(am, vs))

> tryfn(mtcars, select_vars = c( "mpg","disp"), groups = c(am, vs))
# A tibble: 32 x 4
# Groups:   am, vs [4]
      am    vs   mpg  disp
 * <dbl> <dbl> <dbl> <dbl>
 1     1     0  21    160 
 2     1     0  21    160 
 3     1     1  22.8  108 
 4     0     1  21.4  258 
 5     0     0  18.7  360 
 6     0     1  18.1  225 
 7     0     0  14.3  360 
 8     0     1  24.4  147.
 9     0     1  22.8  141.
10     0     1  19.2  168.

看来这会满足您的需求

tryfn <- function(data, select_vars, groups){
  
  data %>% 
    select({{groups}}, {{select_vars}}) %>% 
    group_by(across({{groups}}))
  
}

我们使用across()配合group_by来展开多选

我给你的函数加了一行group_vars <- purrr::map(group_vars, as.symbol)。这确保 group_vars 中的项目将变成符号。

tryfn <- function(data, select_vars,groups, ...){
  
  select_vars <- as.list(rlang::enexpr(select_vars))
  select_vars <- if(length(select_vars) > 1) select_vars[-1] else select_vars
  
  group_vars <- as.list(rlang::enexpr(groups))
  group_vars  <- if(length(group_vars ) > 1) group_vars[-1] else group_vars 
  group_vars <- purrr::map(group_vars, as.symbol)
  
  data %>% select(!!!group_vars,!!!select_vars) %>% group_by(!!!group_vars)
}