3

I'm doing something kinda simple, but tidyeval always puzzles me. In this case, I have a function that plots something and I want to also save it afterwards using the name of the column I'm plotting, something like this:

bar_plot= function(table, col_plot){
    ggplot(table, aes(x=region,
                    y= {{col_plot}})) + 
geom_bar(stat = "identity", fill="steelblue") +
     ggsave(glue('results/{col_plot}.png'))
  
}

The plot has no problems, but I'm not able to save it (doesn't find the object, because it isn't reading it as a string). Tried using quo, enquo, sym, and nothing worked. What is the way to turn my variable name into a string inside the function?

For reproducibility this is enough:

df = data.frame(region = c(1, 2), mean_age = c(20, 30))

Thanks !

6
  • Do you just need to put ggsave in a new line without the + from the previous line? Commented Mar 15, 2022 at 18:12
  • That won't solve the variable problem, though, it still won't compute as a string Commented Mar 15, 2022 at 18:15
  • @danh It saves the plot as 'results/{col_plot}.png' not as 'results/mean_age.png' like OP wants. Commented Mar 15, 2022 at 18:26
  • @Gregor Thomas are you sure? It saves just fine as results/mean_age.png for me. Commented Mar 15, 2022 at 18:28
  • Sorry, I think OP wants to call the function with unquoted names, e.g., bar_plot(df, mean_age). In that case, the ggsave line gives an error object 'mean_age' not found. Commented Mar 15, 2022 at 18:31

2 Answers 2

5

You can do this:

bar_plot <- function(table, col_plot) {
  
  p <- ggplot(table, aes(region, {{col_plot}})) + geom_col(fill = "steelblue")
  
  ggsave(paste0('results/', deparse(substitute(col_plot)), '.png'), p)
  
}

bar_plot(df, mean_age)

So you have:

./results/mean_age.png

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Exactly what I was looking for, thank you! Was harder than expected. Is there a more straightforward way if my function takes the variable name as string as an argument, instead of the variable name without quotes? can I do something like .data[[col_plot]] in the ggplot call if it's a string?
You can use aes_string instead of aes to pass a string
@JuanC yes, since ggplot2 version 3.0 .data[[col_plot]] is a good way to use a string column name in ggplot. aes_string is soft-deprecated. This is also the way its recommended to use ggplot in packages.
Thanks to both of you, I'm clear now! I'll use strings, seems more understandable to me
3

Abstracting out the plotting part and focusing on the file name, I think you can also use rlang::as_name here to convert the symbol into the string you need.

library(ggplot2)

df <- data.frame(region = c(1, 2), mean_age = c(20, 30))

bar_plot <- function(table, col_plot) {
  # ggplot(table, aes(
  #   x = region,
  #   y = {{ col_plot }}
  # )) +
  #   geom_bar(stat = "identity", fill = "steelblue")
  filename <- glue::glue("results/{rlang::as_name(enquo(col_plot))}.png")
  filename
}

bar_plot(df, mean_age)
#> results/mean_age.png

Note that we need to do two things: first wrap the argument col_plot in enquo, so we get mean_age of instead of literally col_plot. Then convert with as_name() to turn mean_age into "mean-age".

2 Comments

Thank you! seems a bit more intuitive than deparse + substitute
With rlang 1.0 you can write rlang::englue("results/{{ col_plot }}.png").

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.