在 magrittr 管道中使用 enquo()

3

我只是想了解这里出了什么问题。在第一个案例(有效)中,我将enquo()处理过的参数分配给一个变量,在第二个案例中,我直接在调用mutate时使用了enquoted参数。

library("dplyr")
df <- tibble(x = 1:5, y= 1:5, z = 1:5)

# works
myfun <- function(df, transformation) {
  my_transformation <- rlang::enquo(transformation)
  df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(my_transformation))
}
myfun(df,exp(value))

# does not work
myfun_2 <- function(df, transformation) {
  df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation)))
}
myfun_2(df,exp(value))
#>Error in mutate_impl(.data, dots) : Column `value` is of unsupported type closure

编辑 以下是更多需要思考的内容 :)

将调用包装到quo()中,看起来表达式被正确地“构建”了。

# looks as if the whole thing should be working
myfun_2_1 <- function(df, transformation) {
  quo(df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation))))
}
myfun_2_1(df,exp(value))

如果你使用 quo(),并将其告诉给 eval_tidy,它就可以正常工作了(如果没有 quo(),它无法正常工作)。
# works
myfun_2_2 <- function(df, transformation) {
  eval_tidy(quo(df %>% 
    gather("key","value", x,y,z) %>% 
    mutate(value = UQ(rlang::enquo(transformation)))))
}
myfun_2_2(df,exp(value))

如果您不使用管道,它仍然有效。
# works
myfun_2_3 <- function(df, transformation) {
  mutate(gather(df,"key","value", x,y,z), value = UQ(rlang::enquo(transformation)))
}
myfun_2_3(df,exp(value))

关于错误信息,当我们尝试传递data.frame不支持的类型时,例如:

mutate(df, value = function(x) x) # Error in mutate_impl(.data, dots) : Column value is of unsupported type closure

我认为在myfun_2中的quosure未被mutate计算,这是一种有趣/非直观的行为。您认为我应该向开发人员报告此问题吗?


顺便提一下,在“gather()”之后的管道序列中查看data.frame时,它显示“value”列的类型为整数。 - eladin
我会将您的问题重命名为:“在magrittr管道中使用enquo()”。 - Lionel Henry
1个回答

6

这个限制在rlang 0.2.0中得到了解决。

具体来说:问题的核心在于magrittr在当前环境的子环境中评估其参数。正是这个环境包含了代词.。从0.2.0开始,使用enquo()及其变体捕获参数现在是词法作用域,也就是它会查找父级环境堆栈以找到要捕获的参数。这解决了magrittr的问题。


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