左对齐两个图形边(ggplot)

我正在使用 ggplot,并且有两个图,我希望将它们显示在彼此的顶部。我用了 gridUltra 的 grid.arrange来堆叠它们。问题是,我希望图的左边缘以及右边缘对齐,而不管轴标签。(问题出现了,因为一个图的标签是短的,而另一个是长的)。

问题:
我怎么能这样做呢? 我没有网格结婚。安排,但 gggplot2是必须的。

我试过的方法:
我尝试使用宽度和高度以及 ncal 和 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)

enter image description here

39622 次浏览

At best this is a hack:

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

It feels really wrong though.

Try this,

 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)

Edit

Here's a more general solution (works with any number of plots) using a modified version of rbind.gtable included in gridExtra

gA <- ggplotGrob(A)
gB <- ggplotGrob(B)
grid::grid.newpage()
grid::grid.draw(rbind(gA, gB))

Here is another possible solution using melt from the reshape2 package, and 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)

enter image description here

I wanted to generalize this for any number of plots. Here is a step-by-step solution using the approach by Baptiste:

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

collect the widths for each grob of each plot

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

use do.call to get the max width

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

asign the max width to each grob

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

plot

do.call("grid.arrange", c(grobs, ncol = 1))

On http://rpubs.com/MarkusLoew/13295 is a really easy solution available (last item) Applied to this problem:

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

you can also use this for both width and height:

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

Using cowplot package:

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

enter image description here

The egg package wraps ggplot objects into a standardised 3x3 gtable, enabling the alignment of plot panels between arbitrary ggplots, including facetted ones.

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)

enter image description here

I know this is an old post, and that it has already been answered, but may I suggest combining @baptiste's approach with purrr to make it nicer-looking:

library(purrr)
list(A, B) %>%
map(ggplotGrob) %>%
do.call(gridExtra::gtable_rbind, .) %>%
grid::grid.draw()

The patchwork package handles this by default:

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

Created on 2019-12-08 by the reprex package (v0.3.0)