21

我正在尝试使用 grid.arrange 在 ggplot 生成的同一页面上显示多个图形。这些图使用相同的 x 数据,但具有不同的 y 变量。由于 y 数据具有不同的比例,这些图具有不同的维度。

我尝试在 ggplot2 中使用各种主题选项来更改绘图大小并移动 y 轴标签,但没有一个可以对齐绘图。我希望将图排列在 2 x 2 正方形中,以便每个图的大小相同并且 x 轴对齐。

下面是一些测试数据:

A <- c(1,5,6,7,9)
B <- c(10,56,64,86,98)
C <- c(2001,3333,5678,4345,5345)
D <- c(13446,20336,24333,34345,42345)
L <- c(20,34,45,55,67)
M <- data.frame(L, A, B, C, D)

我用来绘制的代码:

x1 <- ggplot(M, aes(L, A,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x2 <- ggplot(M, aes(L, B,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x3 <- ggplot(M, aes(L, C,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x4 <- ggplot(M, aes(L, D,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
grid.arrange(x1,x2,x3,x4,nrow=2)

如果您运行此代码,您将看到由于 y 轴单位的长度较大,底部两个绘图的绘图区域较小。

如何使实际的绘图窗口相同?

4

5 回答 5

21

编辑

更简单的解决方案是:1)使用cowplot包(请参阅此处的答案);或 2) 使用egggithub 上提供的包。

# devtools::install_github("baptiste/egg")
library(egg)
library(grid)

g = ggarrange(x1, x2, x3, x4, ncol = 2)
grid.newpage()
grid.draw(g)

原来的

次要编辑:更新代码。

如果您想保留轴标签,那么通过一些摆弄,并从这里借用代码,就可以完成这项工作。

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

# Get the widths
gA <- ggplotGrob(x1)
gB <- ggplotGrob(x2)
gC <- ggplotGrob(x3)
gD <- ggplotGrob(x4)
maxWidth = unit.pmax(gA$widths[2:3], gB$widths[2:3], 
                     gC$widths[2:3], gD$widths[2:3])

# Set the widths
gA$widths[2:3] <- maxWidth
gB$widths[2:3] <- maxWidth
gC$widths[2:3] <- maxWidth
gD$widths[2:3] <- maxWidth

# Arrange the four charts
grid.arrange(gA, gB, gC, gD, nrow=2)

在此处输入图像描述

替代解决方案:包中 有用于将 grobs 组合成一个 grobrbindcbind功能。gtable对于此处的图表,应使用 设置宽度size = "max",但 CRAN 版本的gtable会引发错误。

一种选择是检查grid.arrange绘图,然后使用size = "first"or size = "last"` 选项:

# Get the ggplot grobs
gA <- ggplotGrob(x1)  
gB <- ggplotGrob(x2)
gC <- ggplotGrob(x3)
gD <- ggplotGrob(x4)

# Arrange the four charts
grid.arrange(gA, gB, gC, gD, nrow=2)

# Combine the plots   
g = cbind(rbind(gA, gC, size = "last"), rbind(gB, gD, size = "last"), size = "first")

# draw it
grid.newpage()
grid.draw(g)

第二种选择是从包中获取bind函数。gridExtra

# Get the ggplot grobs
gA <- ggplotGrob(x1)  
gB <- ggplotGrob(x2)
gC <- ggplotGrob(x3)
gD <- ggplotGrob(x4)

# Combine the plots
g = cbind.gtable(rbind.gtable(gA, gC, size = "max"), rbind.gtable(gB, gD, size = "max"), size = "max")

# Draw it
grid.newpage()
grid.draw(g)
于 2012-12-01T07:39:58.073 回答
11

这正是我编写cowplot包的问题。它可以在该包中的一行中完成:

require(cowplot) # loads ggplot2 as dependency
# re-create the four plots
A <- c(1,5,6,7,9)
B <- c(10,56,64,86,98)
C <- c(2001,3333,5678,4345,5345)
D <- c(13446,20336,24333,34345,42345)
L <- c(20,34,45,55,67)
M <- data.frame(L, A, B, C, D)
x1 <- ggplot(M, aes(L, A,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x2 <- ggplot(M, aes(L, B,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x3 <- ggplot(M, aes(L, C,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')
x4 <- ggplot(M, aes(L, D,xmin=10,ymin=0)) + geom_point() + stat_smooth(method='lm')

# arrange into grid and align
plot_grid(x1, x2, x3, x4, align='vh')

结果如下 在此处输入图像描述 :(请注意,cowplot 更改了默认的 ggplot2 主题。如果你真的想的话,你可以恢复灰色。)

作为奖励功能,您还可以在每个图表的左上角添加绘图标签:

plot_grid(x1, x2, x3, x4, align='vh', labels=c('A', 'B', 'C', 'D'))

结果: 在此处输入图像描述

labels我几乎在我制作的每一个多部分图表上都使用该选项。

于 2015-07-04T06:24:00.653 回答
9

我会使用 faceting 来解决这个问题:

library(reshape2)
dat <- melt(M,"L") # When in doubt, melt!

ggplot(dat, aes(L,value)) + 
geom_point() + 
stat_smooth(method="lm") + 
facet_wrap(~variable,ncol=2,scales="free")

例子

注意:外行可能会忽略不同刻面的尺度不同。

于 2012-12-01T05:55:28.197 回答
4

Patchwork是一个新的包,它使得格式化和布局多个 ggplot 变得非常容易。关于它的最好的事情之一是它会自动对齐绘图区域。另外,语法非常简单。

devtools::install_github("thomasp85/patchwork")
library(patchwork)
x1 + x2 + x3 + x4 + plot_layout(ncol = 2)

在此处输入图像描述

查看 GitHub 页面以获取更多示例:https ://github.com/thomasp85/patchwork

于 2018-05-10T22:53:16.823 回答
0

如果您使用 RMarkdown 并编织成 PDF,我有另一种方法。Knitr 在创建 PDF 时提供了绘制子图的功能,它允许您在一个图中有多个图,每个图都有自己的标题。

为此,必须单独显示每个图。通过将cowplot包中的几个函数连接在一起,我制作了以下函数,它可以对齐绘图,同时将它们保持为单独的对象:

plot_grid_split <- function(..., align = "hv", axis= "tblr"){
  aligned_plots <- cowplot::align_plots(..., align=align, axis=axis)
  plots <- lapply(1:length(aligned_plots), function(x){
    cowplot::ggdraw(aligned_plots[[x]])
  })
  invisible(capture.output(plots))
}

这是一个示例,比较正常布局与使用函数:

---
output: pdf_document
header-includes:
   - \usepackage{subfig}
---

```{r}
plot_grid_split <- function(..., align = "hv", axis= "tblr"){
  aligned_plots <- cowplot::align_plots(..., align=align, axis=axis)
  plots <- lapply(1:length(aligned_plots), function(x){
    cowplot::ggdraw(aligned_plots[[x]])
  })
  invisible(capture.output(plots))
}
```

```{r fig-sub, fig.cap='Four Plots Not Aligned', fig.subcap=c('Plot One', 'Plot Two', 'Plot Three', 'Plot Four'), out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}  
library(ggplot2) 
plot <- ggplot(iris, aes(Sepal.Length, Sepal.Width, colour = Species)) +
  geom_point()

plot + labs(title = "A nice title")
plot + labs(caption = "A sample caption")
plot + theme(legend.position = "none")
plot + theme(legend.position = "top")
```  

```{r fig-sub-2, fig.cap='Four Plots Aligned', fig.subcap=c('Plot One', 'Plot Two', 'Plot Three', 'Plot Four'), out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}

x1 <- plot + labs(title = "A nice title")
x2 <- plot + labs(caption = "A sample caption")
x3 <- plot + theme(legend.position = "none")
x4 <- plot + theme(legend.position = "top")

plot_grid_split(x1, x2, x3, x4)
```

在此处输入图像描述

于 2018-03-07T01:28:48.390 回答