如何在ggplot(带图例)中制作一致宽度的图?

jam*_*son 47 r ggplot2

我有一些我想要绘制的不同类别.这些是不同的类别,每个类别都有自己的标签集,但在文档中将它们组合在一起是有意义的.以下给出了一些简单的堆积条形图示例:

df <- data.frame(x=c("a", "b", "c"),
                 y=c("happy", "sad", "ambivalent about life"))
ggplot(df, aes(x=factor(0), fill=x)) + geom_bar()
ggplot(df, aes(x=factor(0), fill=y)) + geom_bar()
Run Code Online (Sandbox Code Playgroud)

问题在于,对于不同的标签,图例具有不同的宽度,这意味着图表具有不同的宽度,如果我制作桌子或\subfigure元素,会导致看起来有点傻.我怎样才能解决这个问题?

有没有办法明确设置绘图或图例的宽度(绝对或相对)?

图1基于x(更宽) 图2基于y(较窄)

San*_*att 37

编辑: 非常容易egg在github上提供包

# install.package(devtools)
# devtools::install_github("baptiste/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)
Run Code Online (Sandbox Code Playgroud)

原创 Udated到ggplot2 2.2.1

这是一个使用gtable包中的函数的解决方案,并侧重于图例框的宽度.(这里可以找到更通用的解决方案.)

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)
Run Code Online (Sandbox Code Playgroud)

如果另外,传说盒子需要是左对齐,并借用一些代码在这里通过@Julius写

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)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

替代方案rbindcbind功能在gtable包grobs组合成一个GROB.对于此处的图表,应使用设置宽度size = "max",但CRAN版本会gtable引发错误.

一个选择:显而易见的是,第二个图中的图例更宽.因此,请使用该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)
Run Code Online (Sandbox Code Playgroud)

左对齐的传说:

# 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)
Run Code Online (Sandbox Code Playgroud)

第二种选择是使用rbindBaptiste的gridExtra包装

# 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)
Run Code Online (Sandbox Code Playgroud)

左对齐的传说:

# 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)
Run Code Online (Sandbox Code Playgroud)


Aar*_*ica 9

cowplot软件包还具有此align_plots功能(输出未显示),

both2 <- align_plots(p1, p2, align="hv", axis="tblr")
p1x <- ggdraw(both2[[1]])
p2x <- ggdraw(both2[[2]])
save_plot("cow1.png", p1x)
save_plot("cow2.png", p2x)
Run Code Online (Sandbox Code Playgroud)

并且还将plot_grid图表保存到同一文件中.

library(cowplot)
both <- plot_grid(p1, p2, ncol=1, labels = c("A", "B"), align = "v")
save_plot("cow.png", both)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


bap*_*ste 8

正如@hadley所说,rbind.gtable应该能够处理这个,

  grid.draw(rbind(ggplotGrob(p1), ggplotGrob(p2), size="last"))
Run Code Online (Sandbox Code Playgroud)

但是,理想情况下size="max",布局宽度应该与某些类型的网格单元不能很好地配合.