12

I have a multiplot figure consisting of 4 plots in a 2x2 configuration. I arranged the plots using the "cowplot" package and the plot_grid function using the code below

plot_grid(p1, p2, p3, p4, align='vh', vjust=1, scale = 1)

where p1-p4 are my 4 plots. The resulting figure has an x-axis label associated with each column in the multiplot:

enter image description here

Does anyone know how I can code a single x-axis label centered at the bottom of the multiplot, either with cowplot or another way?

Jason
  • 892
  • 1
  • 8
  • 19
  • 2
    No data to go with the code. The strategy to use for hacking or embedding an oddball, er I mean 'obscure', package plotting routine is to first determine the plotting paradigm (base, lattice or ggplot) and then do a search for annotation or marginal labeling methods to use with the appropriate primary plotting function. – IRTFM Oct 14 '15 at 01:05

2 Answers2

22

Another option is to use textGrob to add annotations for common x and y labels.

In this example, if you wish to remove the individual axis labels, just include theme(axis.title = element_blank()) in the plot calls. (or, for just y-axis, use theme(axis.title.y=element_blank())).

library(ggplot2)
library(cowplot)
library(grid)
library(gridExtra)

ToothGrowth$dose <- as.factor(ToothGrowth$dose)

#make 4 plots

p1<-ggplot(ToothGrowth, aes(x=dose, y=len)) + 
  geom_boxplot()


p2<-ggplot(ToothGrowth, aes(x=dose, y=supp)) + 
  geom_boxplot()

p3<-ggplot(ToothGrowth, aes(x=supp, y=len)) + 
  geom_boxplot()

p4<-ggplot(ToothGrowth, aes(x=supp, y=dose)) + 
  geom_boxplot()

#combine using cowplot

plot<-plot_grid(p1, p2, p3, p4, align='vh', vjust=1, scale = 1)

#create common x and y labels

y.grob <- textGrob("Common Y", 
                   gp=gpar(fontface="bold", col="blue", fontsize=15), rot=90)

x.grob <- textGrob("Common X", 
                   gp=gpar(fontface="bold", col="blue", fontsize=15))

#add to plot

grid.arrange(arrangeGrob(plot, left = y.grob, bottom = x.grob))

enter image description here

J.Con
  • 4,101
  • 4
  • 36
  • 64
  • If the plot_grid-derived object would contain an extra row, e.g. a legend (plot_grid(plot, get_legend(another_plot), nrow=2); is it possible to get the xgrob inbetween legend and plot? – nouse Jul 03 '18 at 10:22
  • 1
    @nouse try `plot2<-grid.arrange(arrangeGrob(plot, left = y.grob, bottom = x.grob))`, then `plot_grid(plot2, get_legend(another_plot),nrow=2)`. – J.Con Jul 05 '18 at 01:00
  • 1
    Nice! I am not familiar with 'arrangeGrob()'. Which arguments should i use to place the xgrob nearer to the the plot? – nouse Jul 05 '18 at 11:04
  • 1
    @nouse go for `plot_grid(plot2, get_legend(legend_plot),nrow=2, rel_heights = c(6,1))`, adjusting `rel_heights` to suit your needs. – J.Con Jul 05 '18 at 23:16
  • 1
    @J.Con, what if we want to move the labs to the right or the left a little bit? How could we do it? In my case, I have a third column with a legend for each row (plots in the same row share the same legend). Thus, the X-lab should be in the middle between the first and second column without considering the third column. How could I move the x-lab? – Dekike May 24 '20 at 17:52
  • I did this question in StackOverflow related to what I asked you. I would be very grateful if you could help me: https://stackoverflow.com/questions/61990003/how-to-move-x-and-y-labels-to-center-them-in-an-arrange-of-plots-using-arrangeg – Dekike May 24 '20 at 18:47
17

This is a little late but I had the same problem so hopefully the next person to view this question will find this useful.

library(cowplot)
plot<-plot_grid(p1, p2, p3, p4, align='vh', vjust=1, scale = 1)
ggdraw(add_sub(plot, "Label", vpadding=grid::unit(0,"lines"),y=6, x=0.5, vjust=4.5))
Gilad Green
  • 36,708
  • 7
  • 61
  • 95
J.Con
  • 4,101
  • 4
  • 36
  • 64