108

我正在使用 ggplot 并有两个要显示在彼此之上的图表。我用grid.arrangegridExtra 来堆叠它们。问题是我希望图表的左边缘和右边缘对齐,而不管轴标签如何。(出现问题是因为一个图的标签很短,而另一个图的标签很长)。

问题:
我该怎么做?我没有嫁给 grid.arrange 但 ggplot2 是必须的。

我尝试过的:
我尝试使用宽度和高度以及 ncol 和 nrow 来制作 2 x 2 网格并将视觉效果放在对角,然后使用宽度,但我无法在对角获得视觉效果.

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
grid.arrange(A, B, ncol=1)

在此处输入图像描述

4

9 回答 9

146

尝试这个,

 gA <- ggplotGrob(A)
 gB <- ggplotGrob(B)
 maxWidth = grid::unit.pmax(gA$widths[2:5], gB$widths[2:5])
 gA$widths[2:5] <- as.list(maxWidth)
 gB$widths[2:5] <- as.list(maxWidth)
 grid.arrange(gA, gB, ncol=1)

编辑

这是一个更通用的解决方案(适用于任意数量的图),使用rbind.gtable包含的修改版本gridExtra

gA <- ggplotGrob(A)
gB <- ggplotGrob(B)
grid::grid.newpage()
grid::grid.draw(rbind(gA, gB))
于 2012-11-08T19:00:15.410 回答
41

我想将这一点推广到任意数量的地块。这是使用 Baptiste 方法的分步解决方案:

plots <- list(A, B, C, D)
grobs <- list()
widths <- list()

收集每个地块的每个 grob 的宽度

for (i in 1:length(plots)){
    grobs[[i]] <- ggplotGrob(plots[[i]])
    widths[[i]] <- grobs[[i]]$widths[2:5]
}

使用 do.call 获取最大宽度

maxwidth <- do.call(grid::unit.pmax, widths)

为每个 grob 分配最大宽度

for (i in 1:length(grobs)){
     grobs[[i]]$widths[2:5] <- as.list(maxwidth)
}

阴谋

do.call("grid.arrange", c(grobs, ncol = 1))
于 2013-10-11T14:50:57.550 回答
33

使用cowplot包:

A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 

library(cowplot)
plot_grid(A, B, ncol=1, align="v")

在此处输入图像描述

于 2015-10-01T07:45:01.723 回答
12

http://rpubs.com/MarkusLoew/13295上是一个非常简单的解决方案(最后一项)适用于这个问题:

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
grid.draw(rbind(ggplotGrob(A), ggplotGrob(B), size="first"))

您也可以将其用于宽度和高度:

require(ggplot2);require(gridExtra)
A <- ggplot(CO2, aes(x=Plant)) + geom_bar() +coord_flip() 
B <- ggplot(CO2, aes(x=Type)) + geom_bar() +coord_flip() 
C <- ggplot(CO2, aes(x=conc)) + geom_bar() +coord_flip()
D <- ggplot(CO2, aes(x=uptake)) + geom_bar() +coord_flip() 
grid.draw(cbind(
            rbind(ggplotGrob(A), ggplotGrob(B), size="first"),
            rbind(ggplotGrob(C), ggplotGrob(D), size="first"),
            size='first'))
于 2014-04-10T10:06:55.933 回答
10

egg包将 ggplot 对象包装到一个标准化的3x3gtable 中,使绘图面板能够在任意 ggplots 之间对齐,包括多面的。

library(egg) # devtools::install_github('baptiste/egg')
library(ggplot2)

p1 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
  geom_point() 

p2 <- ggplot(mtcars, aes(mpg, wt, colour = factor(cyl))) +
  geom_point() + facet_wrap( ~ cyl, ncol=2, scales = "free") +
  guides(colour="none") +
  theme()

ggarrange(p1, p2)

在此处输入图像描述

于 2016-06-13T00:24:49.687 回答
8

这是使用meltreshape2 包的另一种可能的解决方案,并且facet_wrap

library(ggplot2)
library(reshape2)

dat = CO2[, c(1, 2)]
dat$id = seq(nrow(dat))
mdat = melt(dat, id.vars="id")

head(mdat)
#   id variable value
# 1  1    Plant   Qn1
# 2  2    Plant   Qn1
# 3  3    Plant   Qn1
# 4  4    Plant   Qn1
# 5  5    Plant   Qn1
# 6  6    Plant   Qn1

plot_1 = ggplot(mdat, aes(x=value)) + 
         geom_bar() + 
         coord_flip() +
         facet_wrap(~ variable, nrow=2, scales="free", drop=TRUE)

ggsave(plot=plot_1, filename="plot_1.png", height=4, width=6)

在此处输入图像描述

于 2012-11-08T20:52:39.150 回答
3

patchwork包默认处理这个问题:

library(ggplot2)
library(patchwork)

A <- ggplot(CO2, aes(x = Plant)) + geom_bar() + coord_flip() 
B <- ggplot(CO2, aes(x = Type)) + geom_bar() + coord_flip() 

A / B

reprex 包(v0.3.0)于 2019 年 12 月 8 日创建

于 2019-12-08T19:25:20.353 回答
1

我知道这是一篇旧帖子,并且已经得到了回答,但我可以建议将@baptiste 的方法与purrr使其看起来更好看:

library(purrr)
list(A, B) %>% 
  map(ggplotGrob) %>% 
  do.call(gridExtra::gtable_rbind, .) %>% 
  grid::grid.draw()
于 2018-07-11T16:35:05.140 回答
0

充其量这是一个黑客:

library(wq)
layOut(list(A, 1, 2:16),  list(B, 2:3, 1:16))

不过感觉真的不对。

于 2012-11-08T18:14:27.333 回答