结合公式和整洁的评估(密谋)

时间:2019-04-03 23:11:31

标签: r plotly rlang

我正在努力理解这一点。

下面的内容使我可以“整洁”地过滤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)

现在:

  1. 我假设在这种情况下,enquo(x)至少部分等效于~wt,因为这似乎是这样工作的。但是它们是两个不同的东西(Quosure VS公式)。它们之间是什么关系,为什么上述方法有效?

  2. plotly的公式API的优势在于,如果我要操纵输入值,可以执行类似~wt/2的操作。但是在上面,执行plot_ly(data, x = x, y = x/2)会产生错误。有办法使这项工作吗?

我想普遍的问题是如何最好地将整洁的评估方法与plotly的公式方法结合起来?

1 个答案:

答案 0 :(得分:2)

来自@alistaire的answer

  

plotly R软件包是在rlang之前创建的,它具有自己的非标准评估(NSE)系统,据我所知,大部分仅在示例中进行了说明。

     

当NSE系统横盘整理时,使其正常工作的最快方法是动态重写所有代码,然后对其进行评估。在这里,将整个plotly管道包装在quo中,并在任意位置使用!!替换,然后在其上调用quo_squash将其折叠为单个表达式(而不是嵌套的quoures) ,然后整个调用eval_tidy来实际运行它。

     

plotly中,~用于引用数据集中要可视化的列(@cpsievert)。

在您的示例中,x是一种保证,因此您必须在应用任何基本运算符之前先取消报价。这就是错误消息告诉您的内容:

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(v0.2.1.9000)于2019-04-03创建