【问题标题】:Creating arbitrary panes in ggplot2在 ggplot2 中创建任意窗格
【发布时间】:2011-12-21 01:53:10
【问题描述】:

在基本图形中,我可以通过执行以下操作来创建一个 4 面板的图形窗格:

par(mfrow=c(2,2))
for (i in 1:4){
  plot(density(rnorm(100)))
}

导致

我想用 ggplot2 做同样的事情,但我不知道该怎么做。我不能使用构面,因为与这个简单的示例不同,我的真实数据具有非常不同的结构,我希望两个图是点图,两个是直方图。如何在ggplot2中创建面板或窗格?

【问题讨论】:

标签: r ggplot2


【解决方案1】:

截至 2018 年 7 月,有几个软件包可以帮助很好地创建多面板图。请参阅下面的示例

library(ggplot2)
theme_set(theme_bw())

q1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
q2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
q3 <- ggplot(mtcars) + geom_smooth(aes(disp, qsec))
q4 <- ggplot(mtcars) + geom_bar(aes(carb))

egg package

library(grid)
library(egg)

ggarrange(q1, q2, q3, q4, 
          ncol = 2,
          top = "Plot title",
          bottom = textGrob(
            "This footnote is right-justified",
            gp = gpar(fontface = 3, fontsize = 10),
            hjust = 1, x = 1)
          )
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

cowplot package

library(cowplot)

plot_grid(q1, q2, q3, q4, 
          ncol = 2,
          labels = "AUTO")
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

patchwork package

library(patchwork)

q1 + q2 + q3 + q4 + 
  plot_layout(ncol = 2) +
  plot_annotation(title = "Plot title",
                  subtitle = "Plot subtitle",
                  tag_levels = 'A',
                  tag_suffix = ')')
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

# complex layout 1
q1 + {
  q2 + plot_spacer() + {
    q3 + 
      q4 + 
      plot_layout(ncol = 1)
  }
} +
  plot_layout(ncol = 1)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

# complex layout 2
(q1 | q2 | q3) /
  q4
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'

# bonus: working with grob objects
p1 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear))
table1 <- tableGrob(mtcars[1:6, 1:4])
patchwork::wrap_plots(list(p1, table1), nrow = 1) 

multipanelfigure package

library(magrittr)
library(multipanelfigure)

figure1 <- multi_panel_figure(columns = 2, rows = 2, panel_label_type = "none")
# show the layout
figure1

figure1 %<>%
  fill_panel(q1, column = 1, row = 1) %<>%
  fill_panel(q2, column = 2, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2, row = 2)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
figure1

# complex layout
figure2 <- multi_panel_figure(columns = 3, rows = 3, panel_label_type = "upper-roman")

figure2 %<>%
  fill_panel(q1, column = 1:2, row = 1) %<>%
  fill_panel(q2, column = 3, row = 1) %<>%
  fill_panel(q3, column = 1, row = 2) %<>%
  fill_panel(q4, column = 2:3, row = 2:3)
#> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
figure2

reprex package (v0.2.0.9000) 于 2018 年 7 月 6 日创建。

【讨论】:

    【解决方案2】:

    我认为值得更多关注的实用程序是wq::layOut(注意大写“O”)。就像base::layout 一样,这些图可以有不同的大小,按行和列排列。 layOut 的每个参数都是一个 3 元素列表,由绘图、绘制它的行索引和绘制它的列索引组成。例如:

    library("ggplot2")
    # Generate 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)
    
    wq::layOut(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))
    

    【讨论】:

      【解决方案3】:

      编辑: { Ben Bolker 指出了一个更好的选择——来自gridExtra 包的grid.arrange。但是,如果您是ggplot2 用户,那么 R Cookbook 站点仍然值得点击。 }

      R Cookbook 的 multiplot 函数 on this page 的代码(绝对值得一看)对这类事情很有用。直接从该网站引用:

      multiplot <- function(..., plotlist=NULL, cols) {
          require(grid)
      
          # Make a list from the ... arguments and plotlist
          plots <- c(list(...), plotlist)
      
          numPlots = length(plots)
      
          # Make the panel
          plotCols = cols                       # Number of columns of plots
          plotRows = ceiling(numPlots/plotCols) # Number of rows needed, calculated from # of cols
      
          # Set up the page
          grid.newpage()
          pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
          vplayout <- function(x, y)
              viewport(layout.pos.row = x, layout.pos.col = y)
      
          # Make each plot, in the correct location
          for (i in 1:numPlots) {
              curRow = ceiling(i/plotCols)
              curCol = (i-1) %% plotCols + 1
              print(plots[[i]], vp = vplayout(curRow, curCol ))
          }
      
      }
      

      在 3×2 布局中尝试 6 个地块(JD Long 的四个地块,以及两个额外的地块!):

      set.seed(2)
      q1 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      q2 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      q3 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      q4 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      q5 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      q6 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
      
      multiplot(q1, q2, q3, q4, q5, q6, cols=2)
      

      给出这个数字:

      如果该功能不能完全满足您的需求,至少它为您提供了一个不错的起点!

      【讨论】:

        【解决方案4】:

        以 Josh O'Brien 为例:我很惊讶还没有人在 gridExtra 包中提到 grid.arrange

        library(gridExtra)
        grid.arrange(q1,q2,q3,q4,q5,q6,nrow=3)
        

        这里好像提到了这个:multiple graphs in one canvas using ggplot2

        对我来说,这比记住所有视口的东西要容易得多。

        【讨论】:

        • 伟大的指针。没有什么比已经打包好的功能更好的了,我喜欢它还可以设置为grid.layout() 的选项。
        • grid.arrangemultiplot 进行了一些增强,例如i) 处理网格/格子对象; ii) 与ggsave 兼容; iii) 布局参数; iv) 默认 nrow/ncol; v) arrangeGrob 版本避免立即绘制; vi) 两边标题的占位符; vii) as.table 参数来反转绘图顺序。
        • @baptiste,使用 grid.arrange 绘制 2 个图形并使用 ggsave 保存它们导致仅将一个图形保存在 pdf 文件中。您确定网格与 ggsave 兼容吗?
        • @Eduardo 您在这里有点劫持了一个旧答案,但简而言之:使用ggsave(file = "whatever.pdf", arrangeGrob(p1, p2, p3))gridExtra 的最新版本。 grid.arrange 只显示,arrangeGrob 是你需要存储的对象。 ggsave 在内部跟踪最新打印的 ggplot2,但 grid.arrange 没有。
        【解决方案5】:

        感谢 Andrie 的 cmets 和 Harlan 对我之前的问题 (!) 的回答,我提出了这个解决方案,它完成了我所追求的目标:

        set.seed(2)
        q1 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
        q2 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
        q3 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
        q4 <- ggplot(data.frame(x=rnorm(50)), aes(x)) + geom_density()
        
        grid.newpage()
        pushViewport(viewport(layout=grid.layout(2,2)))
        vplayout <- function(x,y) viewport(layout.pos.row=x,layout.pos.col=y)
        print(q1,vp=vplayout(1,1))
        print(q2,vp=vplayout(1,2))
        print(q3,vp=vplayout(2,1))
        print(q4,vp=vplayout(2,2))
        

        产生:

        【讨论】:

        • 额外的好处:你的情节似乎获得了一种模式。 :)
        猜你喜欢
        • 1970-01-01
        • 2011-03-16
        • 2022-08-13
        • 1970-01-01
        • 1970-01-01
        • 2013-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多