我怎样才能在ggplot中制作一致宽度的图(有传说)? [英] How can I make consistent-width plots in ggplot (with legends)?

查看:128
本文介绍了我怎样才能在ggplot中制作一致宽度的图(有传说)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

问题在于,对于不同的标签,图例具有不同的宽度,这意味着图有不同的宽度,导致看起来有点愚蠢,如果我创建一个表或 \subfigure 元素。如何解决这个问题?



是否有明确设置图或图例宽度(绝对或相对)的方法?





>

 #install.package(devtools)
#devtools :: install_github(baptiste / egg)

library(egg)

p1 < - ggplot(data.frame(x = c(a,b,c),
y = c(happy ),
aes(x =因子(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 to ggplot2 2.2.1



下面是一个使用 gtable 包中的函数的解决方案,重点介绍图例框的宽度。 (可以找到更通用的解决方案

  library(ggplot2)
library(gtable)
library (grid)
library(gridExtra)

#您的地块
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()

#获取gtables
gA< - ggplotGrob(p1)
gB< - ggplotGrob(p2)

#设置宽度
gA $宽度< - gB $宽度

#排列两个图表。
#图例框为中心
grid.newpage()
grid.arrange(gA,gB,nrow = 2)

如果此外,图例框需要左对齐,并从由@Julius编写

  p1< / p> -  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()

#获取宽度
gA< - ggplotGrob(p1)
gB < - ggplotGrob(p2)

#宽度不同的部分
leg1 < - convertX(sum(with(gA $ grobs [ (gB $ grobs [[15]],grobs [[1]] $($)),grobs [[1]] $ widths)),mm)
leg2< - convertX宽度)),mm)

#设置宽度
gA $ widths < - gB $宽度

#添加一个em在
#右边的abs(diff(widths))mm宽度的pty列(gA的较小图例框)
gA $ grobs [[15]]< - gtable_add_cols( gA $ grobs [[15]],单位(abs(diff(c(leg1,leg2))),mm))

#排列两个图表
grid.newpage )
grid.arrange(gA,gB,nrow = 2)



替代解决方案 gtable 包中包含 rbind cbind 函数把grobs合并成一个grob。对于这里的图表,宽度应该使用 size =max来设置,但CRAN版本的 gtable 会抛出一个错误。

一个选项:很明显,第二个图中的图例更宽。因此,使用 size =last选项。

 #Get grob 
gA < - ggplotGrob(p1)
gB < - ggplotGrob(p2)

#合并绘图
g = rbind(gA,gB,size =last)

#绘制
grid.newpage()
grid.draw(g)
$ b

左对齐图例:

 #获取grobs 
gA < - ggplotGrob(p1)
gB < - ggplotGrob(p2)

#宽度不同的部分
leg1 < - convertX(sum(with gA $ grobs [[15]],grobs [[1]] $ widths)),mm)
leg2 < - convertX(sum(with(gB $ grobs [[15]],grobs [ 1]] $ widths)),mm)

#在gb的
#图例框的右边添加一个空白的abs(diff(widths))mm宽度的列(较小的图例框)
gA $ grobs [[15]] <-gtable_add_cols(gA $ grobs [[15]],单位(abs(diff(c(leg1,leg2))),mm ))

#合并
g = rbind(gA,gB,size =last)

#绘制
grid.newpage( )
grid.draw(g)

第二个选项是使用Baptiste的<$ c中的 rbind $ c> gridExtra package

 #获取grobs 
gA< - ggplotGrob( p1)
gB < - ggplotGrob(p2)

#合并图表
g = gridExtra :: rbind.gtable(gA,gB,size =max)

#绘制
grid.newpage()
grid.draw(g)

左对齐图例:

 #获取grobs 
gA< - ggplotGrob( p1)
gB < - ggplotGrob(p2)

#宽度不同的部分
leg1 < - convertX(sum(with(gA $ grobs [[15] ],grobs [[1]] $ widths)),mm)
leg2< - convertX(sum(with(gB $ grobs [[15]],grobs [[1]] $ widths)) ,mm)

#为gA(较小的图例框)添加一个空白的abs(diff(widths))mm宽度右边的
#图例框$ (gA $ grobs [[15]],单位(abs(diff(c(leg1,leg2))),mm))

#合并地块
g = gridExt ra :: rbind.gtable(gA,gB,size =max)

#绘制
grid.newpage()
grid.draw(g)


I've got a few different categories that I want to plot. These are different categories, each with their own set of labels, but which makes sense to group together in the document. The following gives some simple stacked bar chart examples:

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

The problem is that with different labels, the legends have different widths, which means the plots have different widths, leading to things looking a bit goofy if I make a table or \subfigure elements. How can I fix this?

Is there a way to explicitly set the width (absolute or relative) of either the plot or the legend?

解决方案

Edit: Very easy with egg package available at 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)

Original Udated to ggplot2 2.2.1

Here's a solution that uses functions from the gtable package, and focuses on the widths of the legend boxes. (A more general solution can be found 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)

If in addition, the legend boxes need to be left justified, and borrowing some code from here written by @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)

Alternative solutions There are rbind and cbind functions in the gtable package for combining grobs into one grob. For the charts here, the widths should be set using size = "max", but the CRAN version of gtable throws an error.

One option: It should be obvious that the legend in the second plot is wider. Therefore, use the size = "last" option.

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

Left-aligned legends:

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

A second option is to use rbind from Baptiste's gridExtra package

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

Left-aligned legends:

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

这篇关于我怎样才能在ggplot中制作一致宽度的图(有传说)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆