我很难理解这一点。
下面让我以“整洁”的方式过滤我的data.frame,并使用plotly绘制一个图。在这种情况下,我使用plotly的基于公式的API来说明要使用的数据框的哪些列:
library(plotly)
tidy_filter = function(data, x) {
x = enquo(x)
filter(data, !!x > 5)
}
mtcars %>%
tidy_filter(wt) %>%
plot_ly(x = ~wt, y = ~wt)
我可以将它包装在一个函数中以获得相同的结果:
tidy_ply = function(data, x) {
x = enquo(x)
data = filter(data, !!x > 5)
plot_ly(data, x = x, y = x)
}
tidy_ply(mtcars, wt)
现在:
enquo(x)
在这种情况下至少部分相当于~wt
,因为它似乎是如何工作的。但它们是两个不同的东西(quosure VS公式)。它们之间有什么关系,为什么上面的工作呢?~wt/2
这样的事情。但在上面,做plot_ly(data, x = x, y = x/2)
会产生错误。有没有办法让这项工作?我想一般的问题是如何最好地将整洁的评估方法与情节公式方法结合起来?
来自@alistaire的answer:
plotly
R软件包是在rlang
之前创建的,并且有自己的非标准评估(NSE)系统,据我所知,这个系统大多只在示例中记录。当NSE系统横向移动时,让它工作的最快方法是动态重写所有代码然后对其进行评估。在这里,用
plotly
替换在quo
中包装整个!!
管道,无论你喜欢什么,然后在其上调用quo_squash
将其折叠为单个表达式(而不是嵌套的quosures),然后在整个批次上调用eval_tidy
来实际运行它。在
plotly
中,~
用于指代要显示的数据集中的列(@cpsievert)。
在你的例子中,x
是一个quosure因此你必须首先取消引用它在应用任何基本运算符之前。这就是错误消息告诉你的内容:
Error: Base operators are not defined for quosures.
Do you need to unquote the quosure?
# Bad:
myquosure / rhs
# Good:
!!myquosure / rhs
这是一个有效的解决方案:
library(rlang)
library(plotly)
tidy_ply2 <- function(data, x) {
x = enquo(x)
print(x)
data = filter(data, !!x > 5)
# https://rlang.r-lib.org/reference/quasiquotation.html
cat('\nUse qq_show() to debug the effect of unquoting operators\n')
qq_show(plot_ly(data, x = ~!!x, y = ~!!x/2))
# `base::eval` works too
eval_tidy(
quo_squash(
quo({
plot_ly(data, x = ~!!x, y = ~!!x/2)
})
)
)
}
tidy_ply2(mtcars, wt)
#> <quosure>
#> expr: ^wt
#> env: global
#>
#> Use qq_show() to debug the effect of unquoting operators
#> plot_ly(data, x = ~^wt, y = ~(^wt) / 2)
#>
由reprex package创建于2019-04-03(v0.2.1.9000)