3

I'm looking for a way to concatenate a quosure and a string whose result is a quosure. Actually, if I use paste0() and quo_name(), I can do it. But I wonder if there is a more elegant alternative to write a function in my package. This is a generic example:

library(dplyr)

df <- data_frame(
  z_1 = 1,
  z_2 = 2,
  y_1 = 10,
  y_2 = 20
)

get_var <- function(.data, var) {
  xx = enquo(var)

  select(.data, paste0(quo_name(xx), "_1"), paste0(quo_name(xx), "_2"))
}

get_var(df, z)
# A tibble: 1 x 2
    z_1   z_2
  <dbl> <dbl>
1     1     2
gung - Reinstate Monica
  • 11,583
  • 7
  • 60
  • 79
Italo Cegatta
  • 410
  • 4
  • 8

1 Answers1

4

Without a function, this is how you do it using dplyr:

library(dplyr)
df %>%
  select(starts_with("z_"))

You can also create a function and pass in a string for the variable name like this:

get_var= function(df, var){
  df %>%
    select(starts_with(paste0(var, "_")))
}

get_var(df, "z")

Now, the tricky part comes when you are trying to pass in the variable name without quoting it into a function (the R code, not the value it contains). One way of doing it would be deparse + substitute in Base R. This converts the symbol supplied to var to a string, which is convenient for later use within the function:

get_var = function(df, var){
  var_quo = deparse(substitute(var))
  df %>%
    select(starts_with(paste0(var_quo, "_")))
}

Finally, here is how to do the same with enquo and quo_name in rlang/tidyverse package:

library(rlang)
get_var = function(df, var){
  var_quo = quo_name(enquo(var))
  df %>%
    select(starts_with(paste0(var_quo, "_")))
}

get_var(df, z)
get_var(df, y)

Result:

# A tibble: 1 x 2
    z_1   z_2
  <dbl> <dbl>
1     1     2

# A tibble: 1 × 2
    y_1   y_2
  <dbl> <dbl>
1    10    20

Notes:

  1. quosures are quoted expressions that keep track of an environment.
  2. enquo takes a symbol referring to a function's argument, quotes the R code and bundles it with the function's environment in a quosure.
  3. quo_name formats a quosure into a string, which can be used later in the function.
  4. quo_text is similar to quo_name but does not check for whether the input is a symbol.

Check these:

  1. rlang documentation
  2. Non-Standard Evaluation in R
  3. ?enquo
  4. ?quo_name
acylam
  • 18,231
  • 5
  • 36
  • 45
  • If you can pass a variable name to your select, I'll upvote. `starts_with` is the approach I'd use – CPak Sep 13 '17 at 21:31
  • @CPark I see. So you want to be able to pass the variable itself and not a string like `"z"`? For instance, `get_var(df, "z")` would not be satisfactory? – acylam Sep 13 '17 at 22:48
  • 1
    I'm not the OP btw. Basically OP wants to define a function where the data frame and column-to-select are dynamically passed as arguments. – CPak Sep 13 '17 at 22:51
  • @CPak My bad. Does this look more like what OP might have wanted? – acylam Sep 14 '17 at 00:08