Search code examples
rggplot2facet

facet barplot on uneven category


Here is an example data.frame which has 30 unique samples (ID 1 to 30), and each sample has three measurements (at three different thresholds ('G1' column); 5e-03, 5e-05, 5e-08). Each of the 90 observations has a p-value (P column). Finally, each of the thirty samples can belong to one of ten different categories ('G2') [sorry for all the numeric variables!]

 # example data.frame
df <- data.frame(
  'ID' = as.character(unlist(lapply(seq(1:30), function(x) rep(x,3)))),
  'P'  = runif(n = 90, min = 0, max = 1),
  'G1' = as.character(c('5e-03','5e-05','5e-08')),
  'G2' = as.character(unlist(lapply(sample(1:10, size = 30, replace = T), function(x) rep(x,3))))
)

I can generate a nice bar plot using this command;

ggplot(df, aes(x = interaction(ID,G2), y = P, fill = G2)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  facet_grid(. ~ G1)

which looks like this:

Plot 1: image with one facet, and 'G2' visualised using colour

However, what I would really like to do is have two facets; 'G1' on the columns (as it currently is) and, instead of using bar colour to demarcate the 'G2' variable, I would like a second horizontal facet on G2. This is what I have tried:

ggplot(df, aes(x = interaction(ID,G2), y = P, fill = G2)) +
  geom_bar(stat = 'identity') +
  coord_flip() +
  facet_grid(G2 ~ G1)

and it is not right. When I facet on G2, it is plotting all samples in each facet. This is ugly because each sample can only belong to one G2 category. How do I generate the second facet where only bars that belong to that group are plotted? I have tried adjusting the 'drop', 'scale' and 'space' variables in facet_grid, but it does not improve things.

This is what I am looking for - I have manually drawn rectangles over the parts of the plot that should be in the facet. It is essentially the same as Plot 1, except the bars are split into a G2 facet.


Solution

  • First note that since you are facetting with G2 and G1, you don't need the x=interaction(ID,G2) anymore: x=ID is enough.

    By default, all facets of a plot share the same scales for their x and y axes. But you can change that with the scales argument

    ggplot(df, aes(x = ID, y = P, fill = G2)) +
      geom_bar(stat = 'identity') +
      facet_grid(G1 ~ G2, scales="free_x")
    

    Note that I swapped G1 and G2 in the definition of the grid. I don't think it is possible to make it work with coord_flip() though.