使用 arrangeGrob 在堆叠图中均衡 ggplot2 面板高度
equalizing ggplot2 panel heights in a stacked plot with arrangeGrob
我有两组时间序列数据,我想将它们绘制成堆叠排列。到目前为止,我已经能够想出这样的东西:
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 轴标签压扁并勾选
底部绘图上的标签,顶部绘图缺少。
现在,我可以重新使用我用来均衡宽度的技巧了。取消注释行
g1g$heights=g2g$heights
产生以下结果:
这不是我想要的,因为过多的垂直 space 现在出现在地块之间 - 我希望它们相互接触。
我知道我可以将 heights
参数传递给 arrangeGrob,以指定地块的相对高度:
g=arrangeGrob(g1g,g2g,heights=c(1,2))
但我必须 fiddle 处理这些数字,直到它看起来正确。
我想知道是否有一种简单的方法可以在渲染最终 grob 时自动强制两个面板具有相同的高度。
改用 rbind,
grid.draw(rbind(ggplotGrob(g1), ggplotGrob(g2)))
如果你想摆脱中间的 space,从 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)))
我有两组时间序列数据,我想将它们绘制成堆叠排列。到目前为止,我已经能够想出这样的东西:
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 轴标签压扁并勾选
底部绘图上的标签,顶部绘图缺少。
现在,我可以重新使用我用来均衡宽度的技巧了。取消注释行
g1g$heights=g2g$heights
产生以下结果:
这不是我想要的,因为过多的垂直 space 现在出现在地块之间 - 我希望它们相互接触。
我知道我可以将 heights
参数传递给 arrangeGrob,以指定地块的相对高度:
g=arrangeGrob(g1g,g2g,heights=c(1,2))
但我必须 fiddle 处理这些数字,直到它看起来正确。
我想知道是否有一种简单的方法可以在渲染最终 grob 时自动强制两个面板具有相同的高度。
改用 rbind,
grid.draw(rbind(ggplotGrob(g1), ggplotGrob(g2)))
如果你想摆脱中间的 space,从 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)))