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.
use rbind instead,
grid.draw(rbind(ggplotGrob(g1), ggplotGrob(g2)))
and if you want to get rid off the space in-between, it's easier to remove those rows from the gtable than to mess with the plot margins (your manual changes to the theme settings produced an error so I ignored those lines).
grid.newpage()
grid.draw(rbind(ggplotGrob(g1)[-(4:6),], ggplotGrob(g2)[-(1:2),]))
Changing the panel heights has to be done in a separate step, e.g. using this little helper function
g12 <- rbind(ggplotGrob(g1)[-(4:6),], ggplotGrob(g2)[-(1:2),])
resize_heights <- function(g, heights = rep(1, length(idpanels))){
idpanels <- unique(g$layout[grepl("panel",g$layout$name), "t"])
g$heights <- grid:::unit.list(g$heights)
g$heights[idpanels] <- unit.c(do.call(unit, list(heights, 'null')))
g
}
grid.newpage()
grid.draw(resize_heights(g12, c(3,1)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With