首页 > 解决方案 > 如何将变量列表传递给函数,但还要考虑引用和引用

问题描述

我想将变量列表传递给函数,但我对引用和引用感到困惑。

通常,我想在完成某种数据管理后返回一个 df ——在函数应用于多个变量之后。

因为它的功能可以正常工作(只是根据用户堆栈交换对另一个问题的回答稍作修改),但在此示例中调用是重复的。任何建议,指向读数等,我将不胜感激。

library(tidyverse)
library(rlang)
library(tidyselect)

data <- data.frame(ageeeeoo = c(1,NA,3,NA,5), 
                   ageeeaah = c(NA,2,NA,4,NA),
                   numnumd  = c(1,NA,3,NA,5),
                   numfoofe = c(NA,2,NA,4,NA))



newfun <- function (var1) {

var1<-enquo(var1)
data<<-mutate(data,(!!as_name(var1)) := coalesce(!!! syms(vars_select(names(data), 
                                       starts_with(as_name(var1))))))
}


newfun(age)
newfun(num)



  ageeeeoo ageeeaah numnumd numfoofe age num
        1       NA       1       NA   1   1
       NA        2      NA        2   2   2
        3       NA       3       NA   3   3
       NA        4      NA        4   4   4
        5       NA       5       NA   5   5

我尝试查看 dplyr 编程文档和其他一些堆栈交换QA,但引用让我失望。我试过使用 alist 和 list 但得到错误。

listofvars<-c("age","num")

newfun <- function (...) {

data<<-mutate(data,(!!!rlang::syms(...)) := coalesce(!!! syms(vars_select(names(data),
                                            starts_with(!!!quos(...))))))
}


  newfun(listofvars)

标签: rdplyrtidyeval

解决方案


library(tidyverse)
library(rlang)
library(tidyselect)

data <- data.frame(ageeeeoo = c(1,NA,3,NA,5), 
                   ageeeaah = c(NA,2,NA,4,NA),
                   numnumd  = c(1,NA,3,NA,5),
                   numfoofe = c(NA,2,NA,4,NA))



newfun2 <- function (data, ...) {

  vars <- ensyms(..., .named = TRUE)
  needed <- map(
    vars,
    ~vars_select(names(data), starts_with(as_name(.x))) %>% 
    {quo(coalesce(!!!syms(.)))}
  )
  mutate(data, !!!needed)
}

data <- newfun2(data, age, num)

list_of_vars <- exprs(age, num)
data <- newfun2(data, !!!list_of_vars)
data

这首先将输入...作为符号捕获。它可以purrr::map用来生成coalesce操作列表。然后将这些提供给mutate. 我重写了代码,以免修改函数内的全局环境;大多数 R 代码都是这样工作的,因此通常变量不会被更改,除非通过显式赋值。

rlang 帮助和Hadley Wickham 的高级 R是很好的资源。


推荐阅读