Home > OS >  How do I change only certain column's color?
How do I change only certain column's color?

Time:11-27

I am plotting a barchart with two quantitative variables (in two separate columns), a and b, per categorical variables on the x axis. The first 9 categ variables are the months in which certain values had been reached, while the last one is the yearly average, I would like to fill the last two columns (those referring to the yearly average) with a different color than the previous ones, the following code colors all of the bars in the same way, how do I change only those referring to the year average? thank you!

the two values I want to plot are the following:

a= c(10,11,12,13,14,15,16,17,18,14) # (the last one is the average)
b= c(20,19,18,17,16,15,14,13,12,16) # (the last one is the average)

In scale_fill_manual I put the colors in the order I want them to appear on the graph (starting from the left column), but the output doesn't show the desired result for the last two bars, coloring them as the rest of the bars.

Thanks a lot!

df <- data.frame(Mon= c("February", "February", "March", "March", "April", "April", "May", "May", "June", "June", "July", "July", "August", "August", "September", "September", "October", "October", "Year Average to 01/11", "Year Average to 01/11"),
                 Metrics=c('a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b', 'a', 'b'),
                 Values=c(10, 20,11,19,12,18,13,17,14,16,15,15,16,14,17,13,18,12,14,16))


df$Mon <- factor(df$Mon, levels = unique(df$Mon)) # I do this to avoid the re-ordering of the x variables in alphabetical order


ggplot(df) 
  geom_bar(
    aes(x=Mon, y=Values, fill=Metrics, group=Metrics),
    stat='identity', position='dodge'
  ) 
  scale_fill_manual(values=c("#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#9BD4F5",
                             "#6CC4EE",
                             "#1D8ECE",
                             "#2E77BB")
  ) 
  geom_text(
    aes(x=Mon, y=Values, label=Values, fill=Metrics, group=Metrics),
    position = position_dodge(width = 1),
    vjust = 2, size = 3
  ) 
  theme(
    plot.title = element_text(hjust = 0.5, size = 25),
    plot.subtitle = element_text(hjust = 0.5, color = "darkgrey", size = 20),
    axis.title = element_text(size = 20),
    axis.text = element_text(size = 15),
    panel.background = element_rect(fill = "white", color = "white"),
    panel.grid.major.y = element_line(color = "grey"),
    axis.line = element_line(color = "black")
  ) 
  labs(
    x = "", 
    y = "Values", 
    title = "OSAT and RTF Overview", 
    subtitle = "February to October 2022"
  )

CodePudding user response:

You could fill by the interaction of month and metric. This means you need to spoof a legend - in this case, I have hijacked the alpha scale. I would also add a subtle vertical line to make it clear that the last values are averages. Oh, and fix the x labels so that they don't clash with each other.

ggplot(df, aes(Mon, Values))  
  geom_col(aes(fill = interaction(Mon, Metrics), alpha = Metrics), 
           position = "dodge")  
  geom_text(aes(label = Values, group = Metrics), vjust = 2, size = 3,
            position = position_dodge(width = 1))  
  geom_vline(xintercept = 9.5, color = "gray", linetype = 2)  
  scale_fill_manual(values = c(rep("#9BD4F5", 9), "#1D8ECE",
                               rep("#6CC4EE", 9), "#2E77BB"),guide = "none")  
  scale_alpha_manual(values = c(1, 1))  
  guides(alpha = guide_legend(
    override.aes = list(fill = c("#9BD4F5", "#6CC4EE"))))  
  theme_classic(base_size = 20)  
  theme(plot.title = element_text(hjust = 0.5, size = 25),
    plot.subtitle = element_text(hjust = 0.5, color = "darkgrey", size = 20),
    axis.text = element_text(size = 15),
    axis.text.x = element_text(angle = 45, hjust = 1),
    panel.grid.major.y = element_line(color = "grey", linewidth = 0.5),
    axis.line = element_line(color = "black"))  
  labs(title = "OSAT and RTF Overview", x = NULL,
       subtitle = "February to October 2022")

enter image description here

CodePudding user response:

One option would be to use a helper column to be mapped on the fill aes with four categories: "a", "b", "a_avg" and "b_avg". Second create a palette of fill colors as a named vector to assign your desired colors to these categories:

library(ggplot2)

df$fill <- ifelse(grepl("^Year", df$Mon), paste(df$Metrics, "avg", sep = "_"), df$Metrics)

pal_fill <- c(
  "#9BD4F5",
  "#6CC4EE",
  "#1D8ECE",
  "#2E77BB"
)
names(pal_fill) <- c("a", "b", "a_avg", "b_avg")

ggplot(df,  aes(x = Mon, y = Values, fill = fill, group = Metrics))  
  geom_bar(
    stat = "identity", position = position_dodge(width = 1),
  )  
  scale_fill_manual(values = pal_fill, breaks = c("a", "b"))  
  geom_text(
    aes(label = Values),
    position = position_dodge(width = 1),
    vjust = 2, size = 3
  )  
  theme(
    plot.title = element_text(hjust = 0.5, size = 25),
    plot.subtitle = element_text(hjust = 0.5, color = "darkgrey", size = 20),
    axis.title = element_text(size = 20),
    axis.text = element_text(size = 15),
    panel.background = element_rect(fill = "white", color = "white"),
    panel.grid.major.y = element_line(color = "grey"),
    axis.line = element_line(color = "black")
  )  
  labs(
    x = "",
    y = "Values",
    title = "OSAT and RTF Overview",
    subtitle = "February to October 2022"
  )

enter image description here

  • Related