【问题标题】:Multiple ggplots of different sizes多个不同大小的ggplots
【发布时间】:2013-08-27 23:00:28
【问题描述】:

使用gridExtra 包中的grid.arrange 在矩阵中排列多个图相对简单,但是当某些图旨在比别人大?在基础上,我可以使用layout(),如下例所示:

 nf <- layout(matrix(c(1,1,1,2,3,1,1,1,4,5,6,7,8,9,9), byrow=TRUE, nrow=3))
 layout.show(nf)

ggplot plots 的等价物是什么?

一些包含的地块

library(ggplot2)
p1 <- qplot(x=wt,y=mpg,geom="point",main="Scatterplot of wt vs. mpg", data=mtcars)
p2 <- qplot(x=wt,y=disp,geom="point",main="Scatterplot of wt vs disp", data=mtcars)
p3 <- qplot(wt,data=mtcars)
p4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
p5 <- qplot(wt,data=mtcars)
p6 <- qplot(mpg,data=mtcars)
p7 <- qplot(disp,data=mtcars)
p8 <- qplot(disp, y=..density.., geom="density", data=mtcars)
p9 <- qplot(mpg, y=..density.., geom="density", data=mtcars)

【问题讨论】:

标签: r layout ggplot2 gridextra gtable


【解决方案1】:

您可以使用嵌套的arrangeGrob 调用,如下例所示:

library(ggplot2)
library(gridExtra)

p <- ggplot(data.frame(x=1, y=1), aes(x,y)) + geom_point()

grid.arrange(
  arrangeGrob(
    p, 
    arrangeGrob(p, p, nrow=2),
    ncol=2 ,widths=c(2,1)),
  arrangeGrob(p, p ,p ,ncol=3, widths=rep(1,3)),
  nrow=2)

编辑:

gl <- lapply(1:9, function(ii) grobTree(rectGrob(),textGrob(ii)))

grid.arrange(
  arrangeGrob(gl[[1]],
              do.call(arrangeGrob, c(gl[2:5], ncol=2)),
              nrow=1,
              widths=3:2),
  do.call(arrangeGrob, c(gl[6:9], nrow=1, list(widths=c(1,1,1,2)))),
nrow=2, heights=c(2,1))

【讨论】:

  • 你不需要do.call的匿名函数,arrangeGrob的定义中已经有了...
  • @baptiste 我知道并将其与nrow 一起使用,但在尝试传递widths 时出错。
  • 这是因为c() 处理列表的方式。需要使用do.call(arrangeGrob, c(gl[6:9], nrow=1, list(widths=c(1,1,1,2))))
【解决方案2】:

gtable 的替代方案

library(gtable)

gl <- lapply(1:9, function(ii) grobTree(textGrob(ii), rectGrob()))
# gl <- lapply(1:9, function(ii) ggplotGrob(qplot(1,1) + ggtitle(ii)))

gt <- gtable(widths=unit(rep(1,5), "null"),
             heights=unit(rep(1,3), "null"))

gtable_add_grobs <- gtable_add_grob # alias

gt <- gtable_add_grobs(gt, gl, 
                       l=c(1,4,5,4,5,1,2,3,4),
                       r=c(3,4,5,4,5,1,2,3,5),
                       t=c(1,1,1,2,2,3,3,3,3),
                       b=c(2,1,1,2,2,3,3,3,3))
grid.newpage()
grid.draw(gt)

【讨论】:

  • 这似乎是一种流行的方法,但我不知道如何在情节中添加类似 ggplot 的 grobs。 (在 Roland 的示例中,这很简单。)您能解释一下如何添加绘图吗? (我在 OP 中包含了一些示例图。)
  • ggplotGrob 将 ggplot 转换为 grob,在我的示例中有一条使用它的注释行
  • 呃,抱歉失明了。
【解决方案3】:

你可以使用与grid.arrange布局相同的矩阵界面,

library(gridExtra)
library(grid)
gl <- lapply(1:9, function(ii) grobTree(rectGrob(), textGrob(ii)))

grid.arrange(grobs = gl, layout_matrix = rbind(c(1,1,1,2,3),
                                               c(1,1,1,4,5),
                                               c(6,7,8,9,9)))

同样适用于 ggplots;请注意,NA 可用于表示空白单元格。结果是一个gtable,兼容ggsave()

gl <- replicate(9, ggplot(), FALSE)
grid.arrange(grobs = gl, layout_matrix = rbind(c(1,1,1,2,3),
                                               c(1,1,1,4,5),
                                               c(6,7,8,NA,9)))

【讨论】:

    【解决方案4】:

    感谢所有其他答案,但 Didzis Elferts 对连接到 the answer 的 OP 的评论是我发现最容易实现的。

    library(ggplot2)
    p1 <- qplot(x=wt,y=mpg,geom="point",main="Scatterplot of wt vs. mpg", data=mtcars)
    p2 <- qplot(x=wt,y=disp,geom="point",main="Scatterplot of wt vs disp", data=mtcars)
    p3 <- qplot(wt,data=mtcars)
    p4 <- qplot(wt,mpg,data=mtcars,geom="boxplot")
    p5 <- qplot(wt,data=mtcars)
    p6 <- qplot(mpg,data=mtcars)
    p7 <- qplot(disp,data=mtcars)
    p8 <- qplot(disp, y=..density.., geom="density", data=mtcars)
    p9 <- qplot(mpg, y=..density.., geom="density", data=mtcars)
    
    vplayout <- function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)
    
    grid.newpage()
    pushViewport(viewport(layout = grid.layout(3, 5))) # 3 rows, 5 columns
    print(p1, vp = vplayout(1:2, 1:3))  # the big plot covers rows 1:2 and cols 1:3
    print(p2, vp = vplayout(1, 4))
    print(p3, vp = vplayout(1, 5))
    print(p4, vp = vplayout(2, 4))
    print(p5, vp = vplayout(2, 5))
    print(p6, vp = vplayout(3, 1))
    print(p7, vp = vplayout(3, 2))
    print(p8, vp = vplayout(3, 3))
    print(p9, vp = vplayout(3, 4:5))
    

    【讨论】:

    • 这太棒了!有什么方法可以在超级图的顶部添加单个标题?
    【解决方案5】:

    我喜欢lay_out 函数(以前在wq 包中)提供的接口。它采用list(plot, row(s), column(s)) 形式的参数。以您为例:

    lay_out(list(p1, 1:2, 1:3),
           list(p2, 1, 4),
           list(p3, 1, 5),
           list(p4, 2, 4),
           list(p5, 2, 5),
           list(p6, 3, 1),
           list(p7, 3, 2),
           list(p8, 3, 3),
           list(p9, 3, 4:5))
    

    产量:

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

    【讨论】:

    • 这是最简单的解决方案,但layOut 函数似乎不再存在。您知道还有其他直接的选择吗?
    • 谢谢。有没有办法让这个工作结合 ggplot 和非 ggplot 图形?
    • 它应该适用于任何grid 图形,这主要是指ggplotlattice。如果您想使用base 图形,您可以使用gridBase 包。
    猜你喜欢
    • 1970-01-01
    • 2017-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多