6

由于我已更新到 ggplot2 2.0.0,我无法使用 gridExtra 正确排列图表。问题是多面图表将被压缩,而其他图表将扩展。宽度基本上是混乱的。我想以类似于这些单面图的方式排列它们:左对齐两个图形边缘(ggplot)

我放了一个可重现的代码

library(grid) # for unit.pmax()
library(gridExtra)

plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) + 
  geom_point() + 
  facet_grid(. ~ Species) + 
  stat_smooth(method = "lm")

plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) + 
  geom_point(size=2.5)

g.iris <- ggplotGrob(plot.iris) # convert to gtable
g.mpg <- ggplotGrob(plot.mpg) # convert to gtable

iris.widths <- g.iris$widths # extract the first three widths, 
mpg.widths <- g.mpg$widths # same for mpg plot
max.widths <- unit.pmax(iris.widths, mpg.widths)

g.iris$widths <- max.widths # assign max. widths to iris gtable
g.mpg$widths <- max.widths # assign max widths to mpg gtable

grid.arrange(g.iris,g.mpg,ncol=1)

在此处输入图像描述

正如您将看到的,在顶部图表中,第一个方面被扩展,而其他 2 个在右侧被压缩。底部图表未涵盖所有宽度。

会不会是新的 ggplot2 版本弄乱了 gtable 的宽度?

有人知道解决方法吗?

非常感谢

编辑:添加图表图片

我正在寻找类似的东西:

在此处输入图像描述

4

4 回答 4

5

一种选择是将每个绘图按摩成一个 3x3 gtable,其中中央单元格包裹所有绘图面板。

使用来自@SandyMuspratt 的示例

# devtools::install_github("baptiste/egg") 
grid.draw(egg::ggarrange(plots=plots, ncol=1))

在此处输入图像描述

优点是一旦采用这种标准化格式,绘图可以更容易地组合成各种布局,无论面板、图例、轴、条带等的数量如何。

grid.newpage()
grid.draw(ggarrange(plots=list(p1,  p4, p2, p3), widths = c(2,1), debug=TRUE))

在此处输入图像描述

于 2016-04-04T10:47:30.930 回答
1

我不确定您是否仍在寻找解决方案,但这是相当普遍的。我正在使用 ggplot 2.1.0(现在在 CRAN 上)。它基于此解决方案。我把问题分成两部分。首先,我处理图的左侧,确保轴材料的宽度相同。其他人已经这样做了,并且在SO上有解决方案。但我不认为结果看起来很好。我希望面板也可以在右侧对齐。其次,该过程确保面板右侧的列的宽度相同。它通过在每个图的右侧添加适当宽度的列来做到这一点。(可能有更简洁的方法。有 - 请参阅@baptiste 解决方案。)

library(grid)    # for pmax
library(gridExtra) # to arrange the plots
library(ggplot2)   # to construct the plots
library(gtable)   # to add columns to gtables of plots without legends

mpg$g = "Strip text"  

# Four fairly irregular plots: legends, faceting, strips
p1 <- ggplot(mpg, aes(displ, 1000*cty)) + 
  geom_point() + 
  facet_grid(. ~ drv) + 
  stat_smooth(method = "lm")

p2 <- ggplot(mpg, aes(x = hwy, y = cyl, colour = factor(cyl))) + 
  geom_point() + 
  theme(legend.position=c(.8,.6),
        legend.key.size = unit(.3, "cm"))

p3 <- ggplot(mpg, aes(displ, cty, colour = factor(drv))) + 
  geom_point() + 
  facet_grid(. ~ drv) 


p4 <- ggplot(mpg, aes(displ, cty, colour = factor(drv))) + 
  geom_point() + 
  facet_grid(g ~ .) 

# Sometimes easier to work with lists, and it generalises nicely
plots = list(p1, p2, p3, p4)

# Convert to gtables
g = lapply(plots, ggplotGrob) 

# Apply the un-exported unit.list function for grid package to each plot
g.widths = lapply(g, function(x) grid:::unit.list(x$widths)) 


## Part 1: Make sure the widths of left axis materials are the same across the plots
# Get first three widths from each plot
g3.widths <- lapply(g.widths, function(x) x[1:3])

# Get maximum widths for first three widths across the plots
g3max.widths <- do.call(unit.pmax, g3.widths)

# Apply the maximum widths to each plot
for(i in 1:length(plots)) g[[i]]$widths[1:3] = g3max.widths

# Draw it
do.call(grid.arrange, c(g, ncol = 1))


## Part 2: Get the right side of the panels aligned
# Locate the panels
panels <- lapply(g, function(x) x$layout[grepl("panel", x$layout$name), ])

# Get the position of right most panel
r.panel  = lapply(panels, function(x) max(x$r)) # position of right most panel

# Get the number of columns to the right of the panels
n.cols = lapply(g.widths, function(x) length(x)) # right most column

# Get the widths of these columns to the right of the panels
r.widths  <- mapply(function(x,y,z) x[(y+1):z], g.widths, r.panel, n.cols)

# Get the sum of these widths
sum.r.widths <- lapply(r.widths, sum)

# Get the maximum of these widths
r.width = do.call(unit.pmax, sum.r.widths)

# Add a column to the right of each gtable of width 
# equal to the difference between the maximum
# and the width of each gtable's columns to the right of the panel. 
for(i in 1:length(plots)) g[[i]] = gtable_add_cols(g[[i]], r.width - sum.r.widths[[i]], -1)

# Draw it
do.call(grid.arrange, c(g, ncol = 1))

在此处输入图像描述

于 2016-03-07T06:00:40.753 回答
0

取下这两条线并保留其余的,它工作得很好。

g.iris$widths <- max.widths # assign max. widths to iris gtable
g.mpg$widths <- max.widths # assign max widths to mpg gtable

在此处输入图像描述

可能是限制了它们的宽度。

于 2016-01-14T19:13:28.863 回答
0

这很丑陋,但如果你有时间压力,这个 hack 会起作用(不可概括并且取决于绘图窗口的大小)。基本上将顶部图 2 列与右侧的空白图并猜测宽度。

grid.arrange(
    grid.arrange(plot.iris, ggplot() + theme_minimal(),ncol=2, widths = c(.9, .1)),
    plot.mpg, 
    ncol=1
)
于 2016-01-15T02:32:26.607 回答