Search code examples
rggplot2geom-bar

Color X axis in ggplot2 bar plot


I would need help in order to color the x axis of a ggplot2 figure.

Here is what I can manage to do so far :

    head(data)
  x  y group Axis_color
1 A 25     F         G1
2 A 88     G         G1
3 A 88     H         G1
4 A 22     I         G1
5 A 18     J         G1
6 B 54     F         G3

color_list<- c("F"="orange", "G"="darkgreen", "H"="grey", "I"="pink", "J"="purple", "G1"="blue","G2"="red","G3"="green")
ggplot(data, aes(x = x, y = y, fill = group, label = y)) + 
  coord_flip()+
  geom_bar(stat = "identity")

Which gives:

enter image description here

But I would like to as the column "Axis_color" in order to add colors stored in the color_list to the x axis and get:

enter image description here

As you can see I get two different legends axis as well.

Here are the data if it can helps :

structure(list(x = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B", "C", "C", "C", "C", "C", "D", "D", "D", "D", "D", "E", 
"E", "E", "E", "E"), y = c(25, 88, 88, 22, 18, 54, 25, 37, 68, 
72, 36, 84, 17, 64, 48, 15, 17, 72, 61, 25, 66, 10, 18, 99, 63
), group = c("F", "G", "H", "I", "J", "F", "G", "H", "I", "J", 
"F", "G", "H", "I", "J", "F", "G", "H", "I", "J", "F", "G", "H", 
"I", "J"), Axis_color = c("G1", "G1", "G1", "G1", "G1", "G3", 
"G3", "G3", "G3", "G3", "G1", "G1", "G1", "G1", "G1", "G2", "G2", 
"G2", "G2", "G2", "G3", "G3", "G3", "G3", "G3")), row.names = c(NA, 
-25L), class = "data.frame")

Solution

  • The most convenient solution I could come up with that includes a legend would be to use geom_text() to place fake axis labels. If the legend isn't needed I would've recommended ggtext.

    By placing the text at x = -Inf, you place it at the axis' minimum and you can further nudge the text to the outside with hjust. You'd need to turn off clipping in the coordinates for this to work. Alternatively you can also set x = -10 or something, but you'd have to adjust the scale limits and tailor this value to every plot.

    # data <- structure(...) # omitted for brevity
    
    library(ggplot2)
    
    color_list<- c("F"="orange", "G"="darkgreen", "H"="grey", "I"="pink", "J"="purple", "G1"="blue","G2"="red","G3"="green")
    
    ggplot(data, aes(x = y, y = x, fill = group, label = x)) + 
      geom_col() +
      geom_text(data = ~ subset(.x, !duplicated(x)),
                aes(x = -Inf, colour = Axis_color), hjust = 2) +
      scale_fill_manual(values = color_list[1:5]) +
      scale_colour_manual(values = color_list[-c(1:5)]) +
      coord_cartesian(clip = "off") +
      theme(axis.text.y = element_text(colour = NA))
    

    Small sidenote: I replaced geom_bar(stat = "identity") with geom_col() as that seems cleaner, and swapped the x and y aesthetics, removing the need for coord_flip().