使用gtable将宽度相同的ggplot图形(grobs)排列成2x2布局

5

我试图使用grobs和gtable将四个(ggplot2)图形排列成2x2的网格。我不知道如何设置宽度,以及非1xn或nx1的排列方法。

使用以下代码:

data(iris)
a <- ggplot(iris, aes(x=Species, y=Petal.Width)) + geom_boxplot(color="black") + ylab(expression(Foo~Bar~(g~cm^{-3})))
b <- ggplot(iris, aes(x=Species, y=Petal.Length*100)) + geom_boxplot(color="black") + ylab("foobar (mm)")
c <- ggplot(iris, aes(x=Species, y=Sepal.Width)) + geom_boxplot(color="black") + ylab("foobar (%)")
d <- ggplot(iris, aes(x=Species, y=log10(Sepal.Length))) + geom_boxplot(color="black") + ylab("foobar (cm)")

plots <- list(a,b,c,d)
grobs = lapply(plots, ggplotGrob)
g = do.call(rbind, c(grobs, size="first"))

g$widths = do.call(unit.pmax, lapply(grobs, "[[", "widths"))
grid.newpage()
grid.draw(g)

我可以创建以下1x4的排列方式。 1 by 4 plot arrangement 如果我使用grid.arrange来做两栏,对于这4张图来说,它们的宽度是不同的。
如何将图绑定到gtable中以获得4x4的排列?

4 by 4 plot arrangement - unequal widths

# I thought maybe I could cbind, then rbind, but this does not work
plots1 <- list(a,b)
plots2 <- list(c,d)
grobs1 = lapply(plots1, ggplotGrob)
grobs2 = lapply(plots2, ggplotGrob)

g1 = do.call(cbind, c(grobs1, size="first"))
g2 = do.call(cbind, c(grobs2, size="first"))
# g3 = do.call(rbind, c(g1,g2, size="first")) #this does not work

1
library(cowplot); plot_grid(a,b, c, d, ncol=2,align="v") - MLavoie
1
为什么要问呢?为什么不直接发布带有图表的答案,这样我们所有人都可以看到呢? - Mike Wise
3个回答

12

我认为你已经得到了答案。
你的最后一行代码返回了一个错误,但是通过小修改可以得到一个合并的图表,在这个图表中,列之间的宽度相同:

g3 = do.call(rbind, c(list(g1,g2), size="first")) #将g1和g2组合成一个列表 g3

美观/参考附注:
如果你的x轴是相同的,你可以把它从前两个图中去掉。

library(ggplot2); library(gridExtra); library(grid)

# Tweak the margins to use up empty space.  Margins: Top, Right, Bottom, Left
# For reference: a1= top left,    b1= top right 
#                c1= bottom left, d1= bottom right
a1 <- a + theme(axis.title.x = element_blank(), 
                axis.text.x = element_blank(), 
                axis.ticks.x= element_blank(), 
                plot.margin= unit(c(1, 1, -0.5, 0.5), "lines") ) 
b1 <- b + theme(axis.title.x = element_blank(), 
                axis.text.x = element_blank(), 
                axis.ticks.x= element_blank(), 
                plot.margin= unit(c(1, 1, -0.5, 0.5), "lines") ) 
c1 <- c + theme(plot.margin= unit(c(0, 1, 0.5, 0.5), "lines") )  
d1 <- d + theme(plot.margin= unit(c(0, 1, 0.5, 0.5), "lines") )  

grobz <- lapply(list(a1, b1, c1, d1), ggplotGrob)
grobz.plot <- arrangeGrob( grobs = list(rbind(grobz[[1]], grobz[[3]], size = "last"),
                                        rbind(grobz[[2]], grobz[[4]], size = "last")),
                           ncol = 2)
grid.draw(grobz.plot)

grobz

这些StackOverflow的问题对于调整图表非常有帮助:

  • 使用rbind在gtable中设置绘图宽度(Baptiste)[链接]
  • 在gtable中设置相对面板高度(Baptiste)[链接]
  • 设置绘图宽度和图例 [链接]

1
谢谢...我已经搜索了一个小时才找到这个。它完美地运行,并且结合了我一直试图拼凑起来的很多代码。非常好的示例。 - Nova

4
与上述内容非常相似,但使用gtable函数*
library(ggplot2)
pl <- list(ggplot() + xlab("x"), 
           ggplot() + ylab("y"), 
           ggplot() + ylab("y"), 
           ggplot() + ggtitle("title") + xlab("x"))

library(grid)
library(gridExtra)

gl <- lapply(pl, ggplotGrob)
# gt <- cbind(rbind(gl[[1]], gl[[3]]),
#            rbind(gl[[2]], gl[[4]]))

#  alternative to remove x-axes of top row of plots
gt <- cbind(rbind(gl[[1]][1:3,], gl[[3]]),
            rbind(gl[[2]][1:3,], gl[[4]]))

grid.newpage()
grid.draw(gt)

enter image description here

*: 实际上,由于gtable在比较单位时不允许使用pmax,因此这里使用了来自gridExtra开发版本的替代品


1
这对你是否可行?
library(cowplot)
library(ggplot2)
data(iris)
a <- ggplot(iris, aes(x=Species, y=Petal.Width)) + geom_boxplot(color="black") + ylab(expression(Foo~Bar~(g~cm^{-3}))) + theme_grey()
b <- ggplot(iris, aes(x=Species, y=Petal.Length*100)) + geom_boxplot(color="black") + ylab("foobar (mm)") + theme_grey()
c <- ggplot(iris, aes(x=Species, y=Sepal.Width)) + geom_boxplot(color="black") + ylab("foobar (%)") + theme_grey()
d <- ggplot(iris, aes(x=Species, y=log10(Sepal.Length))) + geom_boxplot(color="black") + ylab("foobar (cm)") + theme_grey()
plot_grid(a,b, c, d, ncol=2,align="v")

enter image description here


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