5

I am currently creating several box plots using ggplot2. Every box plot displays similar data, but the ranges of the discrete x axes, as well as the continuous y axes are not always the same. Some box plots only have two discrete x values, others have three or five. In addition, the continuous y axes have very different ranges; some range from 0-80, others from 0-2.5.

Ideally, I would like to get the following output: for every graph, all of the y axes should be the same absolute length, and every discrete "step" along the x axes should be the same absolute length as well.

I have created a simple example using bar graphs instead of box plots that shows the issue:

library(ggplot2)
library(grid)
x1 <- factor(c('a','b','c','d','e'))
y1 <- c(10,20,50,60,80)
df1 <- data.frame(x1,y1)

x2 <- factor(c('a','b'))
y2 <- c(2,3.5)
df2 <- data.frame(x2,y2)

g1 <- ggplot(df1, aes(x = x1, y = y1)) +
  geom_bar(stat='identity')

g2 <- ggplot(df2, aes(x=x2,y=y2)) +
  geom_bar(stat='identity')

grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 1)))   
print(g1, vp = viewport(layout.pos.row = 1, layout.pos.col = 1))         
print(g2, vp = viewport(layout.pos.row = 2, layout.pos.col = 1))

This gives the following output:

enter image description here

Basically, I would like the bottom graph to be only as wide as the a and b segment of the top graph, thereby making every bar in both graphs the same absolute width. Please note that my graphs will be plotted individually, not as part of a grid.

I have tried playing with the aspect ratio using coord_fixed(), but since the y axes have such different ranges there is not a consistent value I was able to use for every graph. Adjusting the actual width of geom_boxplot alters the relative width of the individual boxes, not their absolute width.

I could potentially use the solution to ggplot2 scale_x_continuous limits or absolute using scale_x_discrete, but then I would have to crop the second image.

I have also tried to adjust solutions from other questions, such as Setting absolute size of facets in ggplot2, GGPLOT2: Distance of discrete values of from each end of x-axis, and Formatting positions on discrete scale in ggplot2, but none have worked so far.

Any help would be greatly appreciated!

Edit in response to @tonytonov's answer

Adjusting scale_x_discrete as I mentioned above, and in @tonytonov's answer below, results in the following graph:

enter image description here

However, I would like to just get the bottom part the following graph (I used Inkscape to crop the lower graph):

enter image description here

As mentioned above, I am just plotting the graphs in a grid to show that I would like the absolute lengths of the y axes and the absolute x step lengths to be the same.

Thanks again!

Community
  • 1
  • 1
MSJ
  • 178
  • 1
  • 7

1 Answers1

1

You can "restore" missing categories by adding scale_x_discrete(limits = ), or, even shorter,

g2 + xlim(levels(df1$x1))

And don't use pushViewport for such tasks: take a look at how this can be done with gridExtra.

library(gridExtra)
grid.arrange(g1, g2 + xlim(levels(df1$x1)), nrow = 2)

enter image description here

If you have many plots, you'll have a more general solution by figuring the longest levels beforehand. This approach can then be easily wrapped into a convenience function.

EDIT:

The best I can do to mimic the desired plot is (rectGrob is acting like a dummy placeholder)

grid.arrange(g1, g2, rectGrob(width = NA), 
             layout_matrix = rbind(c(1,1,1,1,1), c(2,2,3,3,3)))

Of course, there's no x axis alignment, but it's a common problem (check this wiki for possible solutions). Another option is to wait for @baptiste :)

enter image description here

tonytonov
  • 25,060
  • 16
  • 82
  • 98
  • Thanks for your answer! This solution is what I meant by adjusting `scale_x_discrete` in my question above. Since I do not need the empty categories, is there a way to keep the bar width etc without having to crop the plot in a different program? I could easily do that, it would just save me a lot of time if I wouldn't have to do that for every graph. Also thank you very much for the `gridExtra` tip! – MSJ Oct 07 '15 at 14:18
  • Ah, I see, that's a different story then. I'll take a look, though I don't expect it's going to be as easy. – tonytonov Oct 07 '15 at 14:55