1
votes

Everything I can find online about tidyeval is either older and not up to date with latest version of tidyverse\dplyr or else doesn't quite apply.

An example tibble is:

df <- tribble(
       ~var1, ~var2, ~var3,
         1,     2,     3,
         4,     5,     6,
         7,     8,     9
        )

I have a small function that I've written:

fun <- function(data, select_var, arrange_var) {
   select_var <- enquo(select_var)
   arrange_var <- enquo(arrange_var)

   data %>%
     select(!!select_var) %>%
     arrange(!!arrange_var)
   }

The function simply selects column(s) and then arranges by row(s).

When I pass the arguments to the function it works fine with a single variable inside of c():

fun(df, 
    c(var1,
      var2)),
    c(var2))

However, when I try to pass it two variables like this:

    fun(df, 
    c(var1,
      var2)),
    c(var1,
      var2))

I get the following error:

Error: incorrect size (282) at position 1, expecting : 141

The closest stack responses I've been able to find are: arrange() doesn't recognize column name parameter and Pass a vector of variable names to arrange() in dplyr

but both of these seem to give answers that included deprecated solutions (e.g., arrange_())

Some great information here: tidyeval resource roundup by Mara Averick

and Separating and Trimming Messy Data the Tidy Way by Paul Oldham

and of course I've dug into: tidyeval

However none of them seem to address this quirk. I've exhausted my resources after spending an afternoon. The code works find in a standard R file, just can't get it to work inside of a function, but about ready to give up, so thought I would see if you wonderful folks could help. Thanks in advance.

1
At least part of this is the different way that select and arrange behave. Compare just select(df, c(var1. var2)) and arrange(df, c(var1. var2)). select gets a pass on vector input for historical reasons that I don't fully understand; it's more the exception than the rule. I am curious if someone figures the way to using splicing to allow vector input rather than dots capture with arrange though.Calum You
If you want to pass multiple variables you need to use enquos instead of enquo or syms instead of sym (if passing column names as strings). Then use the !!! instead of the !! as this splices the input and evaluates it.Croote
It looks like !!! is soft deprecated per message just received: Unquoting language objects with !!!` is soft-deprecated as of rlang 0.3.0. Please use !! instead.`Scott Davidson

1 Answers

3
votes

Replacing arrange_var with ... and specifying the variables without enclosing them in c() makes it work.

library("dplyr")

df <- tribble(
  ~var1, ~var2, ~var3,
  1, 2, 3,
  4, 5, 6,
  7, 8, 9
)

fun <- function(data, select_var, ...) {
  select_var <- enquo(select_var)
  data %>%
    select(!!select_var) %>%
    # You can pass the dots to `arrange` directly
    arrange(...)
}

fun(df, c(var1, var2), var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8
fun(df, c(var1, var2), var1, var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8

Created on 2019-03-08 by the reprex package (v0.2.1)

It turns out that only select supports strings and character vectors. As the documentation says, "This is unlike other verbs where strings would be ambiguous." See the last example for dplyr::select.

# Two alternatives; both work with `select`.
df %>%
  select(var1, var2)
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8
df %>%
  select(c(var1, var2))
#> # A tibble: 3 x 2
#>    var1  var2
#>   <dbl> <dbl>
#> 1     1     2
#> 2     4     5
#> 3     7     8

# `arrange` only works with lists on comma separated unquoted variable names.
df %>%
  arrange(var1, var2)
#> # A tibble: 3 x 3
#>    var1  var2  var3
#>   <dbl> <dbl> <dbl>
#> 1     1     2     3
#> 2     4     5     6
#> 3     7     8     9
df %>%
  arrange(c(var, var2))
#> Error: incorrect size (4) at position 1, expecting : 3

Created on 2019-03-08 by the reprex package (v0.2.1)