【问题标题】:Convert `c(x, y)` as function argument to `c("x", "y")` in R (rlang/tidyevaluation)将 `c(x, y)` 作为函数参数转换为 R 中的 `c("x", "y")` (rlang/tidyevaluation)
【发布时间】:2021-11-01 21:56:42
【问题描述】:

我想让我的函数的用户以 tidyeval 数据屏蔽方式输入变量,即 fun(x, c(y, z)) 而不是 fun("x", c("y", "z")),但是当他们输入像 c(y, z) 这样的参数时,我希望能够将其用作一个字符向量,例如c("y", "z")

对于使用列名,我确实有一个严重过度的解决方法。也就是说,我在dpylr::select() 调用中使用{{,然后提取列名:

fun_overkill <- function(data, cols) {
  data_subset <- dplyr::select(data, {{cols}})
  
  args_as_character_vector <- colnames(data_subset)
  
  args_as_character_vector
}

fun_overkill(mtcars, c(mpg, drat))

显然,这不是最好的方法,并且它不能推广到我的向量参数不代表列名的情况。

我怀疑{rlang} 可能有答案,但有很多选择,我不懂术语。

在创建模型公式时可能会有用,因为您可以在从字符向量创建的字符串上使用 as.formula

rhs <- paste(fun_overkill(mtcars, c(mpg, drat)), collapse = " + ")
lhs <- "~ "
as.formula(paste0(lhs, rhs))

【问题讨论】:

    标签: r rlang tidyeval


    【解决方案1】:

    一种方法是使用enexpr() 捕获表达式的cols 变量(enquo() 也可以),然后使用call_args() 从表达式中获取参数。这些现在是符号列表,因此您需要循环它们以使它们成为带有as_string() 的字符。

    library(rlang)
    
    fun <- function(data, cols) {
      vars <- call_args(enexpr(cols))
      vapply(vars, as_string, character(1), USE.NAMES = FALSE)
    }
    
    (fun(mtcars, c(mpg, drat)))
    #> [1] "mpg"  "drat"
    
    
    rhs <- paste(fun(mtcars, c(mpg, drat)), collapse = " + ")
    lhs <- "~ "
    as.formula(paste0(lhs, rhs))
    #> ~mpg + drat
    

    reprex package (v2.0.1) 于 2021 年 9 月 3 日创建

    公平地说,这里根本不需要 data 参数。它就在那里,因为它在您的示例中就在那里。

    【讨论】:

    • 嗨,很高兴在这里见到你,我记得几个月前你帮助我完成了我为ggplot2 写的那个geom_hurricane 扩展,我对你在数据可视化方面的知识感到惊讶.所以我想我会再次伸出援手,祝你好运。
    • 很好的答案 - 感谢您的帮助和非常快速的响应!
    • 我有一个后续问题 teunbrand。在单个值上使用 call_args 时,您会收到以下错误 Error: 'call' must be a quoted call。你知道这是为什么/我如何将你的函数推广到单值情况吗?
    猜你喜欢
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-01
    • 2020-08-16
    • 2012-03-06
    相关资源
    最近更新 更多