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.
Now, I could recycle the trick I used to equalize the widths. Uncommenting the line
g1g$heights=g2g$heights
yields the following result:
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.

