【问题标题】:Combined plot of ggplot2 (Not in a single Plot), using par() or layout() function? [duplicate]ggplot2 的组合图(不在单个图中),使用 par() 或 layout() 函数? [复制]
【发布时间】:2012-02-28 22:05:10
【问题描述】:

我一直在考虑使用 par() 或 layout() 函数来组合 ggplots。是否可以使用这些功能?

假设我想为散点图绘制 ggplot,为直方图绘制 ggplot。我想结合这两个情节(不是在一个情节中)。是否适用?

我在 R 中尝试了简单的绘图,没有使用 ggplot 函数。它确实有效。

这是来自 Quick-R 的示例,链接:http://www.statmethods.net/advgraphs/layout.html

# 4 figures arranged in 2 rows and 2 columns
attach(mtcars)
par(mfrow=c(2,2))
plot(wt,mpg, main="Scatterplot of wt vs. mpg")
plot(wt,disp, main="Scatterplot of wt vs disp")
hist(wt, main="Histogram of wt")
boxplot(wt, main="Boxplot of wt")

# One figure in row 1 and two figures in row 2
attach(mtcars)
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE))
hist(wt)
hist(mpg)
hist(disp)

但是当我尝试使用 ggplot 并组合绘图时,我没有得到输出。

【问题讨论】:

  • ggplot2 不是基本图形,因此您不能将 ggplot2 和 layout 或 par(mfrow) 结合起来。您需要在 gridExtra 中使用,例如 plot.arrange 等。或者,您可以在网格系统中使用视口。
  • 既然你要求像layout() 这样的东西,你可能想要像grid.arrange() 这样的东西(正如kohske 提到的)。 This linked post(尤其是 Ben Bolker 的回答)会给你一个很好的起点。

标签: r layout ggplot2 par


【解决方案1】:
library(ggplot2)
library(grid)


vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)


plot1 <- qplot(mtcars,x=wt,y=mpg,geom="point",main="Scatterplot of wt vs. mpg")
plot2 <- qplot(mtcars,x=wt,y=disp,geom="point",main="Scatterplot of wt vs disp")
plot3 <- qplot(wt,data=mtcars)
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
plot5 <- qplot(wt,data=mtcars)
plot6 <- qplot(mpg,data=mtcars)
plot7 <- qplot(disp,data=mtcars)

# 4 figures arranged in 2 rows and 2 columns
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 2)))
print(plot1, vp = vplayout(1, 1))
print(plot2, vp = vplayout(1, 2))
print(plot3, vp = vplayout(2, 1))
print(plot4, vp = vplayout(2, 2))


# One figure in row 1 and two figures in row 2
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 2)))
print(plot5, vp = vplayout(1, 1:2))
print(plot6, vp = vplayout(2, 1))
print(plot7, vp = vplayout(2, 2))

【讨论】:

  • 谢谢大家,我的问题已经解决了。
  • 致 Maiasaura,感谢您提供的脚本/代码。但是当我打印 plot1 和 plot2 时出现错误,上面写着“eval(expr,envir,enclos)中的错误:找不到对象'wt'”。但是,我通过在 plot1 和 plot2 中重新排列你的论点来修复它。 plot1
  • @Maiasaura 感谢您的出色回答。如何将标题添加到整个网格中作为主标题。我看到了 grid.text 选项,但在 2 x 4 网格中,它在顶部和中间的位置不太好。
  • 此解决方案应标记为已过时,因为最近从 CRAN 中删除了网格包。
【解决方案2】:

我认为值得更多关注的实用程序是 layOut 以前的 wq 包(注意大写“O”)。它已从 wq 包中删除,因此我将代码放在下面并将其重命名为 lay_out 以匹配典型的 ggplot 样式。就像base::layout 一样,这些图可以有不同的大小,按行和列排列。 lay_out 的每个参数都是一个 3 元素列表,由绘图、绘制它的行索引和绘制它的列索引组成。

例如,使用@Paul McMurdie 的情节,

lay_out(list(plot1, 1, 1),
        list(plot2, 1, 2),
        list(plot3, 2, 1),
        list(plot4, 2, 2),
        list(plot5, 3, 1:2),
        list(plot6, 4, 1:2),
        list(plot7, 1:2, 3))

lay_out = function(...) {    
    x <- list(...)
    n <- max(sapply(x, function(x) max(x[[2]])))
    p <- max(sapply(x, function(x) max(x[[3]])))
    grid::pushViewport(grid::viewport(layout = grid::grid.layout(n, p)))    

    for (i in seq_len(length(x))) {
        print(x[[i]][[1]], vp = grid::viewport(layout.pos.row = x[[i]][[2]], 
            layout.pos.col = x[[i]][[3]]))
    }
} 

(代码来自wq 包的早期版本,来自commit history on the unofficial Github CRAN mirror。)

【讨论】:

  • 我真的很喜欢这个解决方案。 grid.arrange 没有提供很好的绘图位置。
  • @Grego。 wq 包(水质)似乎不再具有layOut() 功能。对吗?
  • @lawyeR 显然是这样。我已将代码添加到我的答案中。
  • 如何安装必要的包?我试过install.packages("layOut")install.packages("lay_out") 无济于事。
  • 啊抱歉从你的 Github 链接中得到的,我没有意识到你已经链接到函数源:)
【解决方案3】:

涉及grid.layout 的答案有效,我已经使用它,并且我赞成它。然而,我通常觉得这个解决方案太乏味且容易出错,而且我怀疑大多数经常这样做的 ggplot2 爱好者已经将它封装在一个函数中。我在之前的搜索中发现了几个这样的包装函数,但我目前的主力解决方案是在 grid addon package called gridExtra 中。它有有用的参数,但默认的行/列设置通常是您首先想要的:

library("ggplot2")
# Generate list of arbitrary ggplots
plot1 <- qplot(data = mtcars, x=wt, y=mpg, geom="point",main="Scatterplot of wt vs. mpg")
plot2 <- qplot(data = mtcars, x=wt, y=disp, geom="point",main="Scatterplot of wt vs disp")
plot3 <- qplot(wt,data=mtcars)
plot4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
plot5 <- qplot(wt,data=mtcars)
plot6 <- qplot(mpg,data=mtcars)
plot7 <- qplot(disp,data=mtcars)
# You might have produced myPlotList using instead lapply, mc.lapply, plyr::dlply, etc 
myPlotList = list(plot1, plot2, plot3, plot4, plot5, plot6, plot7)
library("gridExtra")
do.call(grid.arrange,  myPlotList)

请注意实际的“将我的绘图组合成一个图形”代码是一行(加载 gridExtra 之后)。您可能会争辩说,将图放入列表中是多行的,但实际上我可以选择使用

grid.arrange(plot1, plot2, plot3, plot4, plot5, plot6, plot7)

对于少量的 ggplots,这可能更可取。但是,对于n_plots &gt; 4,您将开始讨厌必须全部命名和键入它们。

【讨论】:

  • 如果你想要两列,例如,由 grid.arrange 产生,最后一行将包含什么?我尝试了 args = list(ncol = 2) 的变体
  • 这里是单行:do.call(grid.arrange, c(myPlotList, list(ncol = 2)))
猜你喜欢
  • 2018-02-02
  • 1970-01-01
  • 2014-02-02
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 2018-10-08
  • 1970-01-01
  • 2021-12-10
相关资源
最近更新 更多