将参数向量的清单作为保证传递给具有purrr和rlang的函数

问题描述

很抱歉标题中的许多介词。与this question,类似,我有一个要传递给类似dplyr::count这样的函数的quasures / arguments:

library(rlang)
suppresspackageStartupMessages(library(dplyr))

q_list <- function(...) {
  enquos(...)
}

my_q_list <- q_list(
  c(cyl,sort = TRUE),c(cyl,gear,sort = TRUE)
)
my_q_list
#> <list_of<quosure>>
#> 
#> [[1]]
#> <quosure>
#> expr: ^c(cyl,sort = TRUE)
#> env:  global
#> 
#> [[2]]
#> <quosure>
#> expr: ^c(cyl,sort = TRUE)
#> env:  global

reprex package(v0.3.0.9001)于2020-09-02创建

使用purrr和rlang,如何将此列表的每次传递传递并执行到count(mtcars,...)

因此最终结果与:

suppresspackageStartupMessages(library(dplyr))
count(mtcars,cyl,sort = TRUE)
#>   cyl  n
#> 1   8 14
#> 2   4 11
#> 3   6  7
count(mtcars,sort = TRUE)
#>   cyl gear  n
#> 1   8    3 12
#> 2   4    4  8
#> 3   6    4  4
#> 4   4    5  2
#> 5   6    3  2
#> 6   8    5  2
#> 7   4    3  1
#> 8   6    5  1

reprex package(v0.3.0.9001)于2020-09-02创建

解决方法

让这件事变得困难的是在这里使用c()。我们确实需要某种rlang对象来保存您的参数。这是一个更改后的功能,用于生成您的列表

q_list <- function(...) {
  q <- enexprs(...)
  transenv <- new_environment(list(c=exprs))
  purrr::map(q,function(x) {
    eval_tidy(x,env = transenv)
  })
}

这将带走您的表达式,并使它们像c()一样对待enexprs()。然后,您可以将这些值注入函数调用中

my_q_list <- q_list(
  c(cyl,sort = TRUE),c(cyl,gear,sort = TRUE)
)

purrr::map(my_q_list,~eval_tidy(quo(count(mtcars,!!!.x))))

如果仅在列表中创建表达式而不使用c()

,这会更容易
my_q_list <- list(
  exprs(cyl,exprs(cyl,sort = TRUE)
)
purrr::map(my_q_list,!!!.x))))
,

sort可以在外面

library(purrr)
list(q_list(cyl),q_list(cyl,gear)) %>% 
  map(~ count(mtcars,!!! .x,sort = TRUE))
#[[1]]
#  cyl  n
#1   8 14
#2   4 11
3   6  7

#[[2]]
#  cyl gear  n
#1   8    3 12
#2   4    4  8
#3   6    4  4
#4   4    5  2
#5   6    3  2
#6   8    5  2
#7   4    3  1
#8   6    5  1