使用arrangeGrob在堆叠图中平衡ggplot2面板高度

4

我有两组时间序列数据,想要以堆叠的方式绘制出来。目前我已经能够得到类似于这样的结果:

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);

下面显示了合并的图。 我将其特别宽而短,以便您可以看到问题:arrangeGrob使绘图高度相等,但这样做会使绘图面板具有不同的高度。 底部面板被底部绘图上的x轴标签和刻度标签挤压,而顶部绘图则没有。

combined plot

现在,我可以重复使用我用来使宽度相等的技巧。取消注释该行即可。
g1g$heights=g2g$heights

产生以下结果:

fix height attempt plot

因为图形之间出现了过多的垂直空间,这不是我想要的——我希望它们相互接触。我知道我可以传递一个“heights”参数给arrangeGrob,以指定图形的相对高度。
g=arrangeGrob(g1g,g2g,heights=c(1,2))

但是我必须调整数字直到看起来正确。

我想知道是否有一种简单的方法可以在最终渲染grobs时自动强制使两个面板具有相同的高度。


抱歉,我的问题中有内联图像,但我不得不将它们转换为链接,因为我的声誉太低了 :/ - Metamorphic
1个回答

8
请使用rbind代替。
grid.draw(rbind(ggplotGrob(g1), ggplotGrob(g2)))

在此输入图片描述

如果你想去除间隔空间,从gtable中删除这些行比调整绘图边距更容易(由于你对主题设置进行的手动更改导致错误,因此我忽略了那些行)。

grid.newpage()
grid.draw(rbind(ggplotGrob(g1)[-(4:6),], ggplotGrob(g2)[-(1:2),]))

在此输入图片描述

更改面板高度必须进行单独的步骤,例如使用此小助手函数。

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)))

enter image description here


谢谢,那是一个很好的解决方案。我特别喜欢现在不必手动编辑主题的功能。顺便说一下,我认为rbind可能是在过去五个月内添加的?因为我必须升级gridExtra和ggplot2才能让它正常工作...我应该记得更经常升级。 - Metamorphic
rbind.gtable 已经存在于 gtable 中多年了,但最近我在 gridExtra 中导出了一个稍微修改过的副本,因为原始版本无法处理这个非常常见的用例。 - baptiste
我明白了。顺便问一下,如果我想让一个图形(面板)的高度是另一个的两倍,有没有办法使用rbind来实现这个效果? - Metamorphic
1
谢谢!您介意举个例子手动调整高度吗?我认为这可能对遇到类似问题的人有用,因为我最初使用的技术使得进行此类调整成为可能...我对“单位”数据类型不是很熟悉,也不知道它有多强大。例如,我注意到有一个“grobheight”单位,这是否意味着我可以将同一表格中另一个grob的高度(或宽度)设置为另一个grob的1.5倍?或者最简单的方法是什么? - Metamorphic
谢谢!我刚刚看到你更新了答案...很抱歉,我忘记将其标记为“已接受”。 - Metamorphic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接