Arrange ggplot plots (grobs with same widths) using gtable to create 2x2 layout

前端 未结 3 641
难免孤独
难免孤独 2021-02-01 11:14

I am attempting to use grobs and gtable to arrange 4 (ggplot2) plots into a 2x2 grid. I don\'t know how to set widths, and also a non- 1xn, or nx1 arrangement.

Using thi

相关标签:
3条回答
  • 2021-02-01 11:36

    would this work for you

    library(cowplot)
    library(ggplot2)
    data(iris)
    a <- ggplot(iris, aes(x=Species, y=Petal.Width)) + geom_boxplot(color="black") + ylab(expression(Foo~Bar~(g~cm^{-3}))) + theme_grey()
    b <- ggplot(iris, aes(x=Species, y=Petal.Length*100)) + geom_boxplot(color="black") + ylab("foobar (mm)") + theme_grey()
    c <- ggplot(iris, aes(x=Species, y=Sepal.Width)) + geom_boxplot(color="black") + ylab("foobar (%)") + theme_grey()
    d <- ggplot(iris, aes(x=Species, y=log10(Sepal.Length))) + geom_boxplot(color="black") + ylab("foobar (cm)") + theme_grey()
    plot_grid(a,b, c, d, ncol=2,align="v")
    

    0 讨论(0)
  • 2021-02-01 11:50

    I think you already had the answer.
    Your last line returns an error, but a small edit results in a combined plot where widths within columns are the same:

    g3 = do.call(rbind, c(list(g1,g2), size="first")) #combine g1 and g2 into a list

    A sidenote for aesthetics/reference:
    If your x-axis is the same, you can drop it from the top two plots.

    library(ggplot2); library(gridExtra); library(grid)
    
    # Tweak the margins to use up empty space.  Margins: Top, Right, Bottom, Left
    # For reference: a1= top left,    b1= top right 
    #                c1= bottom left, d1= bottom right
    a1 <- a + theme(axis.title.x = element_blank(), 
                    axis.text.x = element_blank(), 
                    axis.ticks.x= element_blank(), 
                    plot.margin= unit(c(1, 1, -0.5, 0.5), "lines") ) 
    b1 <- b + theme(axis.title.x = element_blank(), 
                    axis.text.x = element_blank(), 
                    axis.ticks.x= element_blank(), 
                    plot.margin= unit(c(1, 1, -0.5, 0.5), "lines") ) 
    c1 <- c + theme(plot.margin= unit(c(0, 1, 0.5, 0.5), "lines") )  
    d1 <- d + theme(plot.margin= unit(c(0, 1, 0.5, 0.5), "lines") )  
    
    grobz <- lapply(list(a1, b1, c1, d1), ggplotGrob)
    grobz.plot <- arrangeGrob( grobs = list(rbind(grobz[[1]], grobz[[3]], size = "last"),
                                            rbind(grobz[[2]], grobz[[4]], size = "last")),
                               ncol = 2)
    grid.draw(grobz.plot)
    

    These StackOverflow questions are helpful in aligning plots:

    • Using rbind in gtable to set plot width (Baptiste) [link]
    • Relative panel heights in gtable (Baptiste) [link]
    • Plot widths and legends [link]
    0 讨论(0)
  • 2021-02-01 11:57

    Pretty similar to the above, but using gtable functions*

    library(ggplot2)
    pl <- list(ggplot() + xlab("x"), 
               ggplot() + ylab("y"), 
               ggplot() + ylab("y"), 
               ggplot() + ggtitle("title") + xlab("x"))
    
    library(grid)
    library(gridExtra)
    
    gl <- lapply(pl, ggplotGrob)
    # gt <- cbind(rbind(gl[[1]], gl[[3]]),
    #            rbind(gl[[2]], gl[[4]]))
    
    #  alternative to remove x-axes of top row of plots
    gt <- cbind(rbind(gl[[1]][1:3,], gl[[3]]),
                rbind(gl[[2]][1:3,], gl[[4]]))
    
    grid.newpage()
    grid.draw(gt)
    

    *: actually, since gtable doesn't allow the use of pmax when comparing units, this is using a drop-in replacement from the dev version of gridExtra.

    0 讨论(0)
提交回复
热议问题