rlang/quote/ensym (?) a list of arguments to pass to `scale_color_manual()` inside a user-defined function

I have created the below function so that I can input a name and color that can be passed into the function to filter for those two names and then create a custom name-color pairing to pass to the values argument in scale_color_manual():

library(ggplot2) ## for plotting and using the "mpg" data set as an example
library(rlang) ## quoting/unquoting
library(magrittr) ## pipe

create_mpg_plot <- function(a_team, 
                            b_team,
                            a_color,
                            b_color) {
  ateam2 <- ensym(a_team)
  bteam2 <- ensym(b_team)
  
  filtervars <- c(a_team, b_team)
  
  filtervars <- enquo(filtervars)

  ## plot appears but colors are blank as 
  ## ateam2 and bteam2 's values 
  ## aren't evaluated
  vals <- c(ateam2 = a_color,
            bteam2 = b_color)
  
  ## not work
  # vals <- c(!!ateam2 = a_color,
  #           !!bteam2 = b_color)
  
  ## not work
  # vals <- (quo_name(ateam2) = a_color,
  #          quo_name(bteam2) = b_color)

  ## Error: `:=` can only be used 
  ## within a quasiquoted argument  
  # vals <- c(!!ateam2 := a_color,
  #           !!bteam2 := b_color)
  
  mpgplot <- mpg %>% 
    filter(manufacturer %in% !!filtervars) %>% 
    ggplot(aes(displ, cyl)) +
    geom_line(aes(color = manufacturer)) +
    scale_color_manual(values = vals)
  
  return(mpgplot)
}
mpgResult <- create_mpg_plot(a_team = "dodge", a_color = "red",
                             b_team = "chevrolet", b_color = "darkgreen")

mpgResult 

The end result should be a line plot with colored lines (specified by a_color or b_color) corresponding to the team name (a_team, b_team). I want to do this so instead of "dodge" having a "red" colored line as above, I could choose "ford" to have a "yellow" colored line and any other combination, etc.

How can I evaluate the left-hand side of the list properly using tidyeval so that "vals" contains c("dodge" = "red", "chevrolet" = "darkgreen") so it can be parsed correctly by scale_color_manual()? I tried a few different ways in the commented out section inside the function but I feel like I'm missing something, any help would be appreciated!

It seems to work if you use vctrs :package: to get c like function working with quasiquotation

  vals <- vctrs::vec_c(!!ateam2 := a_color,
            !!bteam2 := b_color)

Try

library(ggplot2) ## for plotting and using the "mpg" data set as an example
library(rlang) ## quoting/unquoting
library(magrittr) ## pipe

create_mpg_plot <- function(a_team, 
                            b_team,
                            a_color,
                            b_color) {
  ateam2 <- ensym(a_team)
  bteam2 <- ensym(b_team)
  
  filtervars <- c(a_team, b_team)
  
  filtervars <- enquo(filtervars)
  
  vals <- vctrs::vec_c(!!ateam2 := a_color,
            !!bteam2 := b_color)
  
  mpgplot <- mpg %>% 
    filter(manufacturer %in% !!filtervars) %>% 
    ggplot(aes(displ, cyl)) +
    geom_line(aes(color = manufacturer)) +
    scale_color_manual(values = vals)
  
  return(mpgplot)
}

create_mpg_plot(a_team = "dodge", a_color = "red",
                             b_team = "chevrolet", b_color = "darkgreen")
4 Likes

This is perfect, didn't think about using {vctrs}, thanks a bunch!!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.