Search code examples
rdplyrrlang

selecting column ranges via sym and enquo with dplyr::select


BLUP: Is it possible to use sym/enquo to pass column ranges to dplyr::select?

Consider the following tibble with columns A through E:

library(tibble)
library(dplyr)
set.seed(4)
d = as_tibble(setNames(as.list(rnorm(5)), LETTERS[1:5]))
d
## # A tibble: 1 x 5
##       A      B     C     D     E
##   <dbl>  <dbl> <dbl> <dbl> <dbl>
## 1 0.217 -0.542 0.891 0.596  1.64

I can select a range of columns using the column operator :, e.g.

select(d, B:D)
## # A tibble: 1 x 3
##        B     C     D
##    <dbl> <dbl> <dbl>
## 1 -0.542 0.891 0.596

I can even pass this range as a quosure:

cols = quo(B:D)
select(d, !!cols)
# same result as above

But I can't pass it as a symbol:

colsym = sym("B:D")
select(d, !!enquo(colsym))
## Error in .f(.x[[i]], ...) : object 'A:C' not found

This is problematic when column range selections are being used e.g. inside an R package.

In my real-world example, I'm selecting multiple ranges of 20-40 columns, so I'd like to stick with using the : operator rather than writing out multiple 20-40 element vectors and using enquos (which I assume would work, but I haven't tested it).


Solution

  • You are trying to pass the non-syntactic name B:D as a symbol -- what you want is an expression. You can use rlang::parse_expr to convert a string to an expression:

    cols <- rlang::parse_expr("B:D")
    
    select(d, !!cols)
    ## A tibble: 1 x 3
    #       B     C     D
    #   <dbl> <dbl> <dbl>
    #1 -0.542 0.891 0.596