how to use rlang::as_string() inside of a function?
Asked Answered
A

2

5

I'm writing a function where I supply a variable name as a symbol. At a different step in the function, I want to use the variable name as a string. Per the documentation, rlang::as_string "converts symbols to character strings."

Here is a basic example. This function returns a tibble with a column titled mean.

find_mean <- function(varname){
  tibble(mean = mean(pull(mtcars, {{varname}})))
> find_mean(qsec)
# A tibble: 1 × 1
   mean
  <dbl>
1  17.8

I want to add another column with the variable name as a string, like so:

# A tibble: 1 × 2
   mean variable
  <dbl> <chr>   
1  17.8 qsec   

I thought this would work.

find_mean <- function(varname){
  tibble(mean = mean(pull(mtcars, {{varname}})),
         variable = rlang::as_string({{varname}}))
}

But it returns this error.

> find_mean(qsec)
 Error in ~qsec : object 'qsec' not found 

I know I'm making some basic error regarding rlang's nonstandard evaluation rules, but googling around hasn't helped me figure this out yet.

Allodium answered 1/8, 2021 at 20:34 Comment(0)
U
9

We may use ensym to convert to symbol and then apply the as_string

find_mean <- function(varname){
  v1 <- rlang::as_string(rlang::ensym(varname))
  tibble(mean = mean(pull(mtcars, {{varname}})),
         variable = v1)
}

-testing

find_mean(qsec)
# A tibble: 1 x 2
   mean variable
  <dbl> <chr>   
1  17.8 qsec    

This can be done in base R as well, i.e. with deparse/substitute

> find_mean <- function(varname) deparse(substitute(varname))
 
> find_mean(qsec)
[1] "qsec"
Unreflecting answered 1/8, 2021 at 20:35 Comment(1)
ensym - that's what I was missing! This also worked in my more complicated real use-case. Thanks a lot @akrun. Not the first time you've saved me great frustration.Allodium
E
2

This could also be used. We use enquo to diffuse user-defined arguments and !! bang-bang operator to force-evaluate it. The difference between ensym and enquo is the first one returns a raw-expression whereas the latter returns a quosure, which is an expression bound to an environment. So in order to access the expression and turn it into string we need to use rlang::get_expr and wrap it with either as_string or paste:

library(rlang)

find_mean <- function(varname){
  tibble(mean = mean(pull(mtcars, !!enquo(varname))),
         variable = paste(get_expr(enquo(varname))))
}

# A tibble: 1 x 2
   mean variable
  <dbl> <chr>   
1  17.8 qsec  
Erlond answered 1/8, 2021 at 20:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.