2

I'm posting this as my first question, so bear with me. I have this data frame.

df <- data.frame(Class =  c("Burkholderiales", "Burkholderiales", "Burkholderiales", "unclassified", "Burkholderiales", "Burkholderiales", "Rhodocyclales",   "Burkholderiales", "Burkholderiales", "Burkholderiales", "Rhodocyclales", "Rhodocyclales", "Burkholderiales", "Rhodocyclales",   "Rhodocyclales",   "Rhodocyclales", "Burkholderiales", "Rhodocyclales",   "Rhodocyclales",   "Rhodocyclales", "Burkholderiales", "Burkholderiales", "Burkholderiales", "Burkholderiales", "Rhodocyclales",   "Rhodocyclales",   "Burkholderiales", "Rhodocyclales", "Burkholderiales", "Rhodocyclales"),
Genus = c("unclassified", "unclassified", "unclassified", "unclassified", "unclassified", "unclassified", "unclassified", "unclassified", "unclassified", "Paucibacter", "Dechloromonas", "unclassified", "unclassified", "unclassified", "Dok59", "Dechloromonas", "Hydrogenophaga", "Dechloromonas", "Uliginosibacterium", "Propionivibrio", "Hydrogenophaga", "unclassified", "Hydrogenophaga", "unclassified", "Sulfuritalea", "Dechloromonas", "unclassified", "Propionivibrio", "unclassified", "Dechloromonas"))

I've made a plot using this code

library("ggplot2")
ggplot(df, aes(x = Class, fill = Genus)) +
  geom_bar() +
  coord_flip()

And it looks like this

enter image description here

I want to subcategorize the legend so that t has the name of the class and below it has each color for each genus. For instance, it may look like two legends, one for Rhodocyclales and one for Burkholderiales with the respective genera and colors under them. I'd like to keep the order of colors if possible. Is this possible with ggplot2?

  • The basic design in `ggplot` is [one scale per `aes`thetic](https://groups.google.com/forum/#!topic/ggplot2/lDvsd4yJ0AE). Work-arounds of various degree of ugliness are therefore required, often involving creation of one or more plot object, manipulation of the various components of the object, and then producing a new plot from the manipulated object(s). – Henrik Jun 20 '14 at 21:32

1 Answers1

0

Here is a workaround I've used in the past. It's not perfect, and still requires some tweaking, but at least it separates the legend as you want. Assuming you have the data.frame df as defined above, here is a way to split up the legends.

library(ggplot2)
library(plyr)
library(gtable)
library(gridExtra)

p_list <- dlply(df, .(Class), function(x) {
      library(ggplot2)
      x$Genus  <-  format(x$Genus, width=30)
      ggplot(aes(x = Class, fill = Genus), data=x) + 
      geom_bar() + coord_flip() + ylim(0, 15) +
      scale_x_discrete(labels=function(x) format(x, width = 30))
})
grob_list <- llply(p_list, ggplotGrob)
grid.arrange(grob_list[[1]], grob_list[[2]], grob_list[[3]], ncol=1)

enter image description here

There are two problems remaining:

  1. Colors might not match across plots, so the same Genus in different plots will likely have different colors. You could try to use factors for the Genus field, so categories are the same in each plot.

  2. Since now legends and x-axis labels are in different plots, it's a little tricky to align the two graphs. I added some buffer by setting a constant width with the format function calls. However, as you can see, the plots x-axes are still not properly aligned.

I have to admit, these issues have been a somewhat tedious to solve for me in the past, so I will leave it to you to figure it out. There are a questions in stackoverflow that address these other problems.

JAponte
  • 1,508
  • 1
  • 13
  • 21