我怎样才能让一致的宽度地块在ggplot(有传说)?(How can I make consiste

2019-09-01 07:17发布

我已经得到了我想要绘制了几个不同的类别。 这些都是不同的类别,每个都有自己的一组标签,但在文档中有意义的组合在一起。 下面给出了一些简单的堆积条形图的例子:

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

问题是,有不同的标签,传说有不同的宽度,这意味着该地块有不同的宽度,从而导致事情看起来有点愚蠢的,如果我做一个表或\subfigure的元素。 我怎样才能解决这个问题?

有没有办法明确设置宽度无论是情节还是传说中的(绝对或相对)?

Answer 1:

编辑:很容易与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)

Udated到2.2.1 GGPLOT2

下面是一个使用从功能上解决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)

如果另外,传说盒子需要是左对齐,并借用一些代码在这里通过@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)

替代方案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)

左对齐的传说:

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

第二个选择是使用rbind从巴蒂斯特的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)

左对齐的传说:

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


Answer 2:

作为@hadley建议, rbind.gtable应该能够处理这个问题,

  grid.draw(rbind(ggplotGrob(p1), ggplotGrob(p2), size="last"))

然而,布局宽度应理想地size="max" ,这不能很好地应付与某些类型的网格单元。



Answer 3:

所述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)

plot_grid节省情节相同的文件。

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



Answer 4:

只是偶然,我注意到,他在他的评论暗示阿朗的解决方案还没有被拾起。 我觉得他的简单而有效的方法是真正值得说明。

阿伦建议传说移动到顶部或底部:

ggplot(df, aes(x=factor(0), fill=x)) + geom_bar() + theme(legend.position = "bottom")
ggplot(df, aes(x=factor(0), fill=y)) + geom_bar() + theme(legend.position = "bottom")

现在,该地块具有相同的宽度的要求。 此外,该地块面积在两种情况下同样大小。

如果有更多的因素,甚至更长的标签,它可能有必要玩的传说,例如在两个或多个行显示图例。 theme()guide_legend()有几个参数来控制位置和传说的外观ggplot2



文章来源: How can I make consistent-width plots in ggplot (with legends)?
标签: r ggplot2