在带有 rlang 的表达式的准引用中使用预先存在的字符向量

Using pre-existing character vectors in quasiquotation of an expression with rlang

有时在使用 dplyr 时会有一个列名称的字符向量,用于对数据进行操作,例如:

 cols_of_interest <- c("Petal.Width", "Petal.Length")

dplyr 0.5.0 及更早版本中,针对此问题的推荐方法是使用 verb_ 下划线结构,如下所示:

library("tidyverse")
my_cols <- c("Petal.Width", "Petal.Length")
iris %>%
  select_(.dots = my_cols)

verb_ 函数现已弃用,取而代之的是 rlang 引入的新整洁评估框架 (dplyr.tidyverse.org/articles/programming.html)图书馆。

dplyr 0.7.0 开始,以下工作无需任何特殊调整:

library("tidyverse")
# library("rlang")
my_cols <- c("Petal.Width", "Petal.Length")
iris %>%
  select(my_cols)

请注意,在 dplyr 的开发版本中,情况并非如此

动机

在 Shiny 应用程序中选择列是一个很好的示例用例,这就是使用 verb_ 表示法

的方法
library("shiny")
library("tidyverse")
library("DT")

shinyApp(
  ui = fluidPage(
    selectInput("cols_to_show",
                "Columns to show",
                choices = colnames(iris),
                multiple = TRUE),
    dataTableOutput("verb_table")
  ),
  server = function(input, output){
    output$verb_table <- renderDataTable({
      iris %>%
        select_(.dots = input$cols_to_show)

    })
  }
)

在 0.5.0 之前的 dplyr 中,非标准评估的基础框架是 lazyeval 并且需要特别考虑字符串。 Hadley Wickham 发布了一个全新的 dplyr 版本,带有一个名为 rlang 的新弱点,它为非标准评估提供了一个更一致的框架。这是版本 0.70 - 这是为什么跳过 0.6.0 的解释 - https://blog.rstudio.org/2017/06/13/dplyr-0-7-0/

以下内容现在无需任何特殊考虑即可使用:

library("tidyverse")
my_cols <- c("Petal.Width", "Petal.Length")
iris %>%
  select(my_cols)

请注意,新的 rlang 框架增加了使用 quosures 获得裸符号向量的能力

my_quos <- quos(Petal.Width, Petal.Length)
iris %>%
  select(!!!my_quos)

您可以在此处阅读有关使用 dplyr 编程的更多信息 - http://dplyr.tidyverse.org/articles/programming.html

闪亮比较

library("shiny")
library("tidyverse")
library("DT")
library("rlang")
shinyApp(
  ui = fluidPage(
    selectInput(
      "cols_to_show",
      "Columns to show",
      choices = colnames(iris),
      multiple = TRUE
    ),
    dataTableOutput("verb_table"),
    dataTableOutput("tidyeval_table")
  ),
  server = function(input, output) {
    output$verb_table <- renderDataTable({
      iris %>%
        select_(.dots = input$cols_to_show)

    })

    output$tidyeval_table <- renderDataTable({
      iris %>%
        select(!!!syms(input$cols_to_show))

    })
  }
)

使用 dplyr 0.6,select() 现在可以理解列名和列位置。以前它只会理解后者。所以你不再需要 syms() 因为现在可以工作了:select(mtcars, c("cyl", "disp"), "am").