Search code examples
rggplot2colorsbar-chart

Different color shades for faceted grouped bar plots in ggplot2


I'm trying to give different shades of the same color to the grouped bar plots that are also faceted.

Here is the code and the output that I already have:

temp.data = data.frame (Species  = rep(c("A","B"),each=2, times=2),
                        Status = rep(c("An","Bac"), times=4),
                        Sex = rep(c("Male","Female"), each=4, times=1),
                        Proportion = c(6.86, 7.65, 30.13, 35.71, 7.13, 10.33, 29.24, 31.09))

ggplot(temp.data, aes(x = Species, y = Proportion, fill = Status, alpha = Species)) +
  geom_bar(stat='identity', position = position_dodge(width = 0.73), width=.67) +
  facet_grid(Sex ~ .) + xlab("X title") + 
  ylab("Y title") + 
  scale_fill_manual(name = "Status", labels = c("An","Bac"),
                    values = c("#86a681","#0a3e03")) +
  scale_alpha_manual(values = c(0.6, 1)) +
  theme_light() + theme(legend.title= element_text(size = 8),
                        legend.title.align=0.5,
                        legend.position = c(),
                        legend.background=element_blank(),
                        legend.text=element_text(size=7),
                        legend.key.size = unit(0.6, 'cm'),
                        axis.title.x = element_text(size = 9),
                        axis.title.y = element_text(size = 9),
                        axis.title.y.right = element_text("Sex of groups"),
                        strip.background = element_rect(
                          color="lightgrey", fill="white", size=0.5, linetype="solid"),
                        strip.text.y = element_text(color = "darkgrey", face = "bold"))

enter image description here

However, I couldn't find an answer here to give different colors for different bar groups. I came up with the scale_alpha_manual() function eventually but it can't be given colors manually, it should be the alpha scales of defined "fill". Therefore, this question also isn't a duplicate question here.

Here's how the desired output should seem like (preferably with the legends): enter image description here

Thanks a lot in advance.


Solution

  • You can use the ggnewscale package. Below, I made subsets of the data for species A and B separately. Then, I made the species A bars with one set of colours and then called new_scale_fill() which initializes a new fill scale. Then, I made the species B bars with different colours. Both bars will have an associated set of colours and a legend that can be set with scale_fill_manual().

    library(ggnewscale)
    library(ggplot2)
    library(dplyr)
    temp.data = data.frame (Species  = rep(c("A","B"),each=2, times=2),
                            Status = rep(c("An","Bac"), times=4),
                            Sex = rep(c("Male","Female"), each=4, times=1),
                            Proportion = c(6.86, 7.65, 30.13, 35.71, 7.13, 10.33, 29.24, 31.09))
    
    tempA <- temp.data %>% filter(Species == "A")
    tempB <- temp.data %>% filter(Species == "B")
    
    
    ggplot() +
      geom_bar(data = tempB, 
               mapping = aes(x = Species, y = Proportion, fill = Status), 
               stat='identity', 
               position = position_dodge(width = 0.73), 
               width=.67) +
      scale_fill_manual(name = "Species", 
                        labels = c("An","Bac"),
                        values = c("#86a681","#0a3e03"),
                        guide = guide_legend(override.aes = list(fill=c("gray75", "gray25")))) + 
      new_scale_fill() + 
      geom_bar(data = tempA, 
               mapping = aes(x = Species, y = Proportion, fill = Status), 
               stat='identity', 
               position = position_dodge(width = 0.73), 
               width=.67, show.legend=FALSE) +
      scale_fill_manual(name = "Species A: Status", 
                        labels = c("An","Bac"),
                        values = c("brown2","brown4")) +
      facet_grid(Sex ~ .) + 
      xlab("X title") + 
      ylab("Y title") + 
      theme_light() + theme(legend.title= element_text(size = 8),
                            legend.title.align=0.5,
                            legend.position = c(),
                            legend.background=element_blank(),
                            legend.text=element_text(size=7),
                            legend.key.size = unit(0.6, 'cm'),
                            axis.title.x = element_text(size = 9),
                            axis.title.y = element_text(size = 9),
                            axis.title.y.right = element_text("Sex of groups"),
                            strip.background = element_rect(
                              color="lightgrey", fill="white", linewidth=0.5, linetype="solid"),
                            strip.text.y = element_text(color = "darkgrey", face = "bold"))
    

    Created on 2023-04-26 with reprex v2.0.2