首页 文章

在ggplot中对齐绘图区域

提问于
浏览
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轴单位的长度较大,底部两个图的绘图区域较小 .

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

5 回答

  • 21

    我会使用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")
    

    Example

    注意:外行人可能会错过刻面之间的比例不同 .

  • 9

    Edit

    更简单的解决方案是:1)使用 cowplot 包(见这里的答案);或2)使用github上提供的 egg 包 .

    # devtools::install_github("baptiste/egg")
    library(egg)
    library(grid)
    
    g = ggarrange(x1, x2, x3, x4, ncol = 2)
    grid.newpage()
    grid.draw(g)
    

    Original

    Minor edit: 更新代码 .

    如果你想保留轴标签,然后使用here中的一些摆弄和借用代码,这就完成了工作 .

    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)
    

    enter image description here

    ALTERNATIVE SOLUTIONS: gtable 包中有 rbindcbind 函数,用于将grob组合成一个grob . 对于此处的图表,应使用 size = "max" 设置宽度,但 gtable 的CRAN版本会引发错误 .

    一种选择是检查 grid.arrange 图,然后使用 size = "first" 或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)
    

    第二个选项是从 gridExtra 包中 bind ing函数 .

    # 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)
    
  • 8

    这正是我编写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')
    

    这是结果:
    enter image description here
    (注意牛皮图改变了默认的ggplot2主题 . 如果你真的想要,你可以回到灰色的那个 . )

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

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

    结果:
    enter image description here

    我几乎在每个多部分图表上使用了 labels 选项 .

  • 3

    Patchwork 是一个新的包,它可以很容易地格式化和布局多个ggplots . 关于它的最好的事情之一是它自动对齐绘图区域 . 另外,语法非常简单 .

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

    enter image description here

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

  • 0

    如果您使用RMarkdown并编织为PDF,我有另一种方法 . Knitr在创建PDF时提供plot subfigures的功能,允许您在绘图中包含多个数字,每个数字都有自己的 Headers .

    为此,每个绘图必须单独显示 . 通过将 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))
    }
    
    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")
    
    
    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)
    
    
    
    ![enter image description here](https://i.stack.imgur.com/tQmD9.png)
    
    
    >您可以在这篇文章中了解有关R中的子图的更多信息 . 此外,您可以查看knitr选项以阅读有关子图块的块选项的更多信息:https://yihui.name/knitr/options/

相关问题