Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Align plot areas in ggplot

Tags:

I am trying to use grid.arrange to display multiple graphs on the same page generated by ggplot. The plots use the same x data but with different y variables. The plots come out with differing dimensions due to the y-data having different scales.

I have tried using various theme options within ggplot2 to change the plot size and move the y axis label but none have worked to align the plots. I want the plots arranged in a 2 x 2 square so that each plot is the same size and the x-axes align.

Here is some test data:

A <- c(1,5,6,7,9) B <- c(10,56,64,86,98) C <- c(2001,3333,5678,4345,5345) D <- c(13446,20336,24333,34345,42345) L <- c(20,34,45,55,67) M <- data.frame(L, A, B, C, D) 

And the code that I am using to plot:

x1 <- ggplot(M, aes(L, A,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x2 <- ggplot(M, aes(L, B,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x3 <- ggplot(M, aes(L, C,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x4 <- ggplot(M, aes(L, D,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') grid.arrange(x1,x2,x3,x4,nrow=2) 

If you run this code, you will see that the bottom two plots have a smaller plot area due to the greater length of the y-axes units.

How do I make the actual plot windows the same?

like image 349
user1868064 Avatar asked Dec 01 '12 05:12

user1868064


2 Answers

Edit

Simpler solutions are: 1) use the cowplot package (see answer here); or 2) use egg package available on github.

# devtools::install_github("baptiste/egg") library(egg) library(grid)  g = ggarrange(x1, x2, x3, x4, ncol = 2) grid.newpage() grid.draw(g) 

Original

Minor edit: Updating code.

If you want to keep the axis labels, then with some fiddling, and borrowing code from here, this does the job.

library(ggplot2) library(gtable) library(grid) library(gridExtra)  # Get the widths gA <- ggplotGrob(x1) gB <- ggplotGrob(x2) gC <- ggplotGrob(x3) gD <- ggplotGrob(x4) maxWidth = unit.pmax(gA$widths[2:3], gB$widths[2:3],                       gC$widths[2:3], gD$widths[2:3])  # Set the widths gA$widths[2:3] <- maxWidth gB$widths[2:3] <- maxWidth gC$widths[2:3] <- maxWidth gD$widths[2:3] <- maxWidth  # Arrange the four charts grid.arrange(gA, gB, gC, gD, nrow=2) 

enter image description here

ALTERNATIVE SOLUTIONS: There are rbind and cbind functions in the gtable package for combining grobs into one grob. For the charts here, the widths should be set using size = "max", but the CRAN version of gtable throws an error.

One option is to examine the grid.arrange plot, then use size = "first" or size = "last"` options:

# Get the ggplot grobs gA <- ggplotGrob(x1)   gB <- ggplotGrob(x2) gC <- ggplotGrob(x3) gD <- ggplotGrob(x4)  # Arrange the four charts grid.arrange(gA, gB, gC, gD, nrow=2)  # Combine the plots    g = cbind(rbind(gA, gC, size = "last"), rbind(gB, gD, size = "last"), size = "first")  # draw it grid.newpage() grid.draw(g) 

A second option is to binding functions from gridExtra package.

# Get the ggplot grobs gA <- ggplotGrob(x1)   gB <- ggplotGrob(x2) gC <- ggplotGrob(x3) gD <- ggplotGrob(x4)  # Combine the plots g = cbind.gtable(rbind.gtable(gA, gC, size = "max"), rbind.gtable(gB, gD, size = "max"), size = "max")  # Draw it grid.newpage() grid.draw(g) 
like image 189
Sandy Muspratt Avatar answered Sep 27 '22 19:09

Sandy Muspratt


That's exactly the kind of problem for which I wrote the cowplot package. It can be done in one line in that package:

require(cowplot) # loads ggplot2 as dependency # re-create the four plots A <- c(1,5,6,7,9) B <- c(10,56,64,86,98) C <- c(2001,3333,5678,4345,5345) D <- c(13446,20336,24333,34345,42345) L <- c(20,34,45,55,67) M <- data.frame(L, A, B, C, D) x1 <- ggplot(M, aes(L, A,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x2 <- ggplot(M, aes(L, B,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x3 <- ggplot(M, aes(L, C,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm') x4 <- ggplot(M, aes(L, D,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')  # arrange into grid and align plot_grid(x1, x2, x3, x4, align='vh') 

This is the result: enter image description here (Note that cowplot changes the default ggplot2 theme. You can get the gray one back though if you really want to.)

As a bonus feature, you can also add plot labels in the top-left corner of each graph:

plot_grid(x1, x2, x3, x4, align='vh', labels=c('A', 'B', 'C', 'D')) 

Result: enter image description here

I use the labels option on virtually every multi-part graph I make.

like image 38
Claus Wilke Avatar answered Sep 27 '22 20:09

Claus Wilke