3

Sometimes when working with dplyr one has a character vector of column names that's to be used to operate on data, for instance:

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

In dplyr 0.5.0 and earlier, the recommended approach to this problem was to use the verb_ underscore construct as follows:

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

The verb_ functions are now deprecated in favour of the new tidy evaluation framework (dplyr.tidyverse.org/articles/programming.html) introduced by the rlang library.

As of dplyr 0.7.0 the following works without any special accommodations:

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

Note that in development builds of dplyr, this was not the case

Motivation

Selecting columns in Shiny apps is a good example use case, this is how one could do it using verb_ notation

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)

    })
  }
)

2 Answers2

3

In pre 0.5.0 dplyr the underlying framework for non-standard evaluation was lazyeval and required special consideration for strings. Hadley Wickham released a fundamentally new version of dplyr with a new underbelly called rlang which provides a more consistent framework for non-standard evaluation. This was version 0.70 - here's an explanation of why 0.6.0 was skipped - https://blog.rstudio.org/2017/06/13/dplyr-0-7-0/

The following now works without any special considerations:

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

Note that the new rlang framework adds the ability to have a vector of naked symbols using quosures

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

You can read more about programming with dplyr here - http://dplyr.tidyverse.org/articles/programming.html

Comparison in Shiny

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))

    })
  }
)
  • It only became clear that this was about a particular package named `rlang` after you posted an answer to your question. Hence my downvote for the question. – IRTFM May 15 '17 at 07:11
  • @42- it's not about rlang, it's about dplyr and the tidyeval framework. I don't see anything wrong with the question. – Lionel Henry May 15 '17 at 11:46
1

With dplyr 0.6, select() now understands both column names and column positions. Previously it would only understand the latter. So you don't need syms() anymore because this now works: select(mtcars, c("cyl", "disp"), "am").

Lionel Henry
  • 6,652
  • 27
  • 33
  • I didn't make my question explicit enough that I was asking about the problem of programming with dplyr, where column names can't be given interactively as string but instead a pre-existing character vector exists. – Charlie Joey Hadley May 16 '17 at 08:25
  • 4
    Your answer above is the most general one. In general, programming in dplyr amounts to building quoted expressions. So character vectors of column names should indeed be transformed to symbols with `rlang::syms()` (or any other suitable way, e.g. `lapply(x, as.name))`. `select()` is an exception because it now accepts strings. – Lionel Henry May 16 '17 at 10:06
  • so I wrote this answer/question against 0.6.0 and there are some (AWESOME) changes in the actually released 0.70 version – Charlie Joey Hadley Jun 18 '17 at 19:20