Unquoting Shiny Inputs for dplyr functions

I'm trying to use a shiny selectInput("sort_var", "Sort on..", choices = colnames(df)) value inside a dplyr pipe so the dataframe is sorted by the selected variable with arrange, but I'm struggling to follow the recommended tidyeval quoting and unquoting of inputs because the shiny input is already quoted and so the following code doesn't seem to work...

sorted_df <- reactive({
  sort <- quo(input$sort_var)
  df %>% 
    arrange(!!sort)
})

The following code does what I'm looking for..

sorted_df <- reactive({
  df %>%
    arrange(.[[grep(paste0("^", input$sort_var, "$"), colnames(df))]])
})

But I'd be interested to know if there is a workable tidyeval procedure for this.

Cheers!

There's no need to unquote here. You can use arrange_at to pass the character vector.

library(magrittr)
library(dplyr)
input <- list(sort_var = "gear")

mtcars %>% 
  arrange_at(.vars = input$sort_var)
2 Likes

but of course! thanks a lot.

what about for use with the wt argument of top_n?

df %>%
  top_n(n = 10, wt = input$sort_var)

If I understand lazy evaluation correctly (very big, tenuous assumption), then quo is for taking expressions and quoting them (delaying evaluation), while sym intended to take characters and convert them to expressions (with delayed evaluation).

Since you start with a character in input$sort_var, I think what you're aiming for is

library(dplyr)

input <- list(sort_var = "mpg")

sorta <- rlang::sym(input$sort_var)

mtcars %>% 
  top_n(n = 2, wt = !!sorta)
2 Likes

What if we need to sort by "cyl,desc(gear)"?

if I use
ui:
textInput("sort_columns","Columns to sort by","cyl,gear"),

server:
s_column <- reactive({
unlist(strsplit(input$sort_columns,split=","))
})

mtcars %>% dplyr::arrange_at(.vars = s_column())

works, but not

ui:
textInput("sort_columns","Columns to sort by","cyl,desc(gear)"),

You can use rlang::parse_exprs() here to capture multiple expressions and then supply them to an arrange() function. Expressions should be separated with a semi-colon but you can use a str_replace_all() so that users can type it as they normally would.

library(tidyverse)

arrange_input <- "cyl, desc(gear)"

arrange_expr <- arrange_input %>% 
  str_replace_all(",", ";") %>% 
  rlang::parse_exprs()

mtcars %>% 
  arrange(!!!arrange_expr) # need 3 exclamations here
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> 2  30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 4  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
#> 5  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
#> 6  32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 7  30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 8  33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 9  27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> 10 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
#> 11 21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> 12 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> 13 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 14 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 15 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
#> 16 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
#> 17 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
#> 18 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
#> 19 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> 20 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#> 21 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
#> 22 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
#> 23 16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
#> 24 17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
#> 25 15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
#> 26 10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
#> 27 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
#> 28 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
#> 29 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
#> 30 15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
#> 31 13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
#> 32 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2

Created on 2019-05-14 by the reprex package (v0.2.1)

This is quite helpful! Thanks so much!