Home > Enterprise >  How to programmatically implement flexibility to either apply a column or use a single color to fill
How to programmatically implement flexibility to either apply a column or use a single color to fill

Time:11-05

I am creating a custom function that generates bar plots using ggplot2 and geom_col().

My objective is to enable the function to dynamically assign either a single color or a color based on a grouping variable to the fill aesthetic. Here's the code I've developed:

library(ggplot2)
library(dplyr)
library(RColorBrewer)

f1 <- function(data, x, y, z, single_color=FALSE, color="red") {
  
  data <- data %>% 
    count({{x}})
  
  if (single_color) {
    p <- ggplot(data, aes(x = factor({{ x }}), y = {{ y }}))  
      geom_col(width = 0.6, fill = color)  
      theme_minimal()
  } else {
    p <- ggplot(data, aes(x = factor({{ x }}), y = {{ y }}, fill = factor({{ z }})))  
      geom_col(width = 0.6)  
      theme_minimal()  
      scale_fill_brewer(palette = "Set1")
  }
  
  return(p)
}

f1(mtcars, cyl, n, cyl, single_color=TRUE, color="blue")
f1(mtcars, cyl, n, cyl, single_color=FALSE)

enter image description here

I'm contemplating whether there's a more straightforward method, such as:

f1 <- function(data, x, y, z) {
  
  z <- ensym(z)
  
  ggplot(data, aes(x = factor({{x}}), y = {{y}}, fill= !!z))  
    geom_col(width = 0.6)  
    scale_fill_brewer(palette = "Set1") 
}

To summarize my question: Is it possible for z to be both a column name and a string simultaneously?

Related link:

CodePudding user response:

If I understand you correctly, you want the argument z to be either a symbol representing a column name, or a string representing a color. I guess this is possible, though it's a little convoluted:

library(ggplot2)

f1 <- function(data, x, y, z) {
  is_column <- deparse(substitute(z)) %in% names(data)
  ggplot(data, aes(x = factor({{x}}), y = {{y}}))  
    do.call("geom_col", c(list(width = 0.6),
                        if(is_column) list(mapping = aes(fill = factor({{z}}))),
                        if(!is_column) list(fill = z)))
}

Testing we get

f1(mtcars, cyl, mpg, cyl)

and

f1(mtcars, cyl, mpg, "blue")

  • Related