编辑:使用egg 包非常简单
# install.packages("egg")
library(egg)
p1 <- ggplot(data.frame(x=c("a","b","c"),
y=c("happy","sad","ambivalent about life")),
aes(x=factor(0),fill=x)) +
geom_bar()
p2 <- ggplot(data.frame(x=c("a","b","c"),
y=c("happy","sad","ambivalent about life")),
aes(x=factor(0),fill=y)) +
geom_bar()
ggarrange(p1,p2, ncol = 1)
原创更新至 ggplot2 2.2.1
这是一个使用 gtable 包中的函数的解决方案,并侧重于图例框的宽度。 (可以找到更通用的解决方案here。)
library(ggplot2)
library(gtable)
library(grid)
library(gridExtra)
# Your plots
p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar()
p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar()
# Get the gtables
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# Set the widths
gA$widths <- gB$widths
# Arrange the two charts.
# The legend boxes are centered
grid.newpage()
grid.arrange(gA, gB, nrow = 2)
如果另外,图例框需要左对齐,借用@Julius写的here的一些代码
p1 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=x)) + geom_bar()
p2 <- ggplot(data.frame(x=c("a","b","c"),y=c("happy","sad","ambivalent about life")),aes(x=factor(0),fill=y)) + geom_bar()
# Get the widths
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# The parts that differs in width
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")
# Set the widths
gA$widths <- gB$widths
# Add an empty column of "abs(diff(widths)) mm" width on the right of
# legend box for gA (the smaller legend box)
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))
# Arrange the two charts
grid.newpage()
grid.arrange(gA, gB, nrow = 2)
替代解决方案 gtable 包中有 rbind 和 cbind 函数,用于将 grobs 组合成一个 grob。对于此处的图表,应使用size = "max" 设置宽度,但gtable 的CRAN 版本会引发错误。
一个选项:很明显,第二个情节中的图例更宽。因此,请使用size = "last" 选项。
# Get the grobs
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# Combine the plots
g = rbind(gA, gB, size = "last")
# Draw it
grid.newpage()
grid.draw(g)
左对齐图例:
# Get the grobs
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# The parts that differs in width
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")
# Add an empty column of "abs(diff(widths)) mm" width on the right of
# legend box for gA (the smaller legend box)
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))
# Combine the plots
g = rbind(gA, gB, size = "last")
# Draw it
grid.newpage()
grid.draw(g)
第二种选择是使用 Baptiste 的 gridExtra 包中的 rbind
# Get the grobs
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# Combine the plots
g = gridExtra::rbind.gtable(gA, gB, size = "max")
# Draw it
grid.newpage()
grid.draw(g)
左对齐图例:
# Get the grobs
gA <- ggplotGrob(p1)
gB <- ggplotGrob(p2)
# The parts that differs in width
leg1 <- convertX(sum(with(gA$grobs[[15]], grobs[[1]]$widths)), "mm")
leg2 <- convertX(sum(with(gB$grobs[[15]], grobs[[1]]$widths)), "mm")
# Add an empty column of "abs(diff(widths)) mm" width on the right of
# legend box for gA (the smaller legend box)
gA$grobs[[15]] <- gtable_add_cols(gA$grobs[[15]], unit(abs(diff(c(leg1, leg2))), "mm"))
# Combine the plots
g = gridExtra::rbind.gtable(gA, gB, size = "max")
# Draw it
grid.newpage()
grid.draw(g)