使用未知变量名称的dplyr mutate管道

3
我正在尝试使用dplyr中的mutate与动态变量名。我在SO上找到了几篇文章(这里这里这里),使我更接近但还没有找到可行的解决方案。我认为缺少的不多,但我需要你的帮助。
这是一个非常类似于我的问题的可重现示例。我有两个字段的表格,其中一个被称为AD或任何其他名称。这个字段必须是一个因子,但可以是字符或整数。我的函数需要将其转换为因子。
library(dplyr)

t1 <- data.frame(f1 = 1:4, AD = 1:4)
t2 <- data.frame(f1 = 1:4, FC = 1:4)

ff <- function(tt){

  # find the variable name
  if(any(colnames(tt)=="AD")){
    vv <- quo(AD)
  } else {
    vv <- colnames(tt) %>% .[.!="f1"]
    vv <- enquo(vv)
  }

  # make the mutate
  tt %>% mutate(!!quo_name(vv) := as.factor(!!vv))      
}

在之前提到的链接的帮助下,我成功地让函数适用于包含AD的表格(使用了我以前不知道的quo!!:=函数)。

ff(tt=t1) %>% str
'data.frame':   4 obs. of  2 variables:
 $ f1: int  1 2 3 4
 $ AD: Factor w/ 4 levels "1","2","3","4": 1 2 3 4

这个很好用。但当我发送一个未知变量名的表格时:
ff(tt=t2) %>% str
'data.frame':   4 obs. of  2 variables:
 $ f1: int  1 2 3 4
 $ FC: Factor w/ 1 level "FC": 1 1 1 1

我的FC现在只有一个因素是错误的。

我认为问题出在第二个选项中设置的vv方式上,它给我带来了错误的env值:

quo(AD)
<quosure>
  expr: ^AD
  env:  global


vv <- colnames(tt) %>% .[.!="f1"]
enquo(vv)
<quosure>
  expr: ^"FC"
  env:  empty

有什么办法可以解决我的问题吗?我愿意采用基本的R语言解决方案,但是它必须能够适应长的管道处理过程。

1个回答

4

在那里不需要使用enquo,它是用于将作为参数传递的值转换为quosure。相反,您需要将字符串转换为符号。为此,可以使用as.name()rlang::sym()

ff <- function(tt){

  # find the variable name
  if(any(colnames(tt)=="AD")){
    vv <- quo(AD)
  } else {
    vv <- colnames(tt) %>% .[.!="f1"]
    vv <- as.name(vv)
  }

  # make the mutate
  tt %>% mutate(!!quo_name(vv) := as.factor(!!vv))      
}

谢谢,看起来我在AD部分也可以使用as.namevv <- as.name("AD")。那么为什么还需要quo,我应该更喜欢哪一个? - Bastien
1
quo() 创建一个 quosure,它不仅捕获表达式/符号,还捕获环境。在这种情况下,您并不真正关心捕获环境,因为您只想在 mutate 链的数据上下文中评估符号。如果您有比列名更复杂的表达式,则必须使用比 as.name() 更高级的东西。 - MrFlick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接