equalizing ggplot2 panel heights in a stacked plot with arrangeGrob

Viewed 1059

I've got two sets of time-series data that I want to plot in a stacked arrangement. So far I've been able to come up with something like this:

library(ggplot2);
library(gridExtra);

t=1:100; s=sin(t/10); c=cos(t/10);
g1=ggplot()+theme_bw()+geom_line(aes(x=t,y=s))+ylab(NULL)
g2=ggplot()+theme_bw()+geom_line(aes(x=t,y=c))+ylab("Cosine")+xlab("Time")

# get rid of the top plot's axis labels
g1=g1+theme(
  axis.text.x=element_blank(),
  panel.margin = unit(0,"null")
  );
g1=g1+labs(x=NULL);

# zero bottom margin of top plot
g1$theme$plot.margin[3]=unit(0,"null");

# zero top margin of bottom plot
g2$theme$plot.margin[1]=unit(0,"null");

# this trick equalizes the width of the two plot panels
g1g=ggplotGrob(g1);
g2g=ggplotGrob(g2);
g1g$widths=g2g$widths

# however, equalizing the heights of the panels is not so simple as
# the following:
# g1g$heights=g2g$heights

g=arrangeGrob(g1g,g2g)

plot(g)   #ggsave("out.svg",g,width=5,height=1.5);

The combined plot is shown below. I made it particularly wide and short so that you could see the problem: arrangeGrob equalizes the plot heights, but doing so makes the plot panels have different heights. The bottom panel gets squished by the x axis label and tick labels on the bottom plot, which the top plot lacks.

combined plot

Now, I could recycle the trick I used to equalize the widths. Uncommenting the line

g1g$heights=g2g$heights

yields the following result:

fix height attempt plot

This is not what I want because of the excessive vertical space which now appears between the plots - I had wanted them to be touching.

I know that I could pass a heights argument to arrangeGrob, to specify the relative heights of the plots:

g=arrangeGrob(g1g,g2g,heights=c(1,2))

But then I have to fiddle with the numbers until it looks right.

I'm wondering if there's an easy way to automatically force just the two panels to have the same height when the final grob is rendered.

1 Answers
Related