Side-by-side plots with ggplot2

后端 未结 13 2471
轮回少年
轮回少年 2020-11-22 02:06

I would like to place two plots side by side using the ggplot2 package, i.e. do the equivalent of par(mfrow=c(1,2)).

For example, I would like to have t

相关标签:
13条回答
  • 2020-11-22 02:32

    Any ggplots side-by-side (or n plots on a grid)

    The function grid.arrange() in the gridExtra package will combine multiple plots; this is how you put two side by side.

    require(gridExtra)
    plot1 <- qplot(1)
    plot2 <- qplot(1)
    grid.arrange(plot1, plot2, ncol=2)
    

    This is useful when the two plots are not based on the same data, for example if you want to plot different variables without using reshape().

    This will plot the output as a side effect. To print the side effect to a file, specify a device driver (such as pdf, png, etc), e.g.

    pdf("foo.pdf")
    grid.arrange(plot1, plot2)
    dev.off()
    

    or, use arrangeGrob() in combination with ggsave(),

    ggsave("foo.pdf", arrangeGrob(plot1, plot2))
    

    This is the equivalent of making two distinct plots using par(mfrow = c(1,2)). This not only saves time arranging data, it is necessary when you want two dissimilar plots.


    Appendix: Using Facets

    Facets are helpful for making similar plots for different groups. This is pointed out below in many answers below, but I want to highlight this approach with examples equivalent to the above plots.

    mydata <- data.frame(myGroup = c('a', 'b'), myX = c(1,1))
    
    qplot(data = mydata, 
        x = myX, 
        facets = ~myGroup)
    
    ggplot(data = mydata) + 
        geom_bar(aes(myX)) + 
        facet_wrap(~myGroup)
    

    Update

    the plot_grid function in the cowplot is worth checking out as an alternative to grid.arrange. See the answer by @claus-wilke below and this vignette for an equivalent approach; but the function allows finer controls on plot location and size, based on this vignette.

    0 讨论(0)
  • 2020-11-22 02:32

    Update: This answer is very old. gridExtra::grid.arrange() is now the recommended approach. I leave this here in case it might be useful.


    Stephen Turner posted the arrange() function on Getting Genetics Done blog (see post for application instructions)

    vp.layout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
    arrange <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
     dots <- list(...)
     n <- length(dots)
     if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
     if(is.null(nrow)) { nrow = ceiling(n/ncol)}
     if(is.null(ncol)) { ncol = ceiling(n/nrow)}
            ## NOTE see n2mfrow in grDevices for possible alternative
    grid.newpage()
    pushViewport(viewport(layout=grid.layout(nrow,ncol) ) )
     ii.p <- 1
     for(ii.row in seq(1, nrow)){
     ii.table.row <- ii.row 
     if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
      for(ii.col in seq(1, ncol)){
       ii.table <- ii.p
       if(ii.p > n) break
       print(dots[[ii.table]], vp=vp.layout(ii.table.row, ii.col))
       ii.p <- ii.p + 1
      }
     }
    }
    
    0 讨论(0)
  • 2020-11-22 02:35

    There is also multipanelfigure package that is worth to mention. See also this answer.

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

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

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

    Created on 2018-07-06 by the reprex package (v0.2.0.9000).

    0 讨论(0)
  • 2020-11-22 02:36

    In my experience gridExtra:grid.arrange works perfectly, if you are trying to generate plots in a loop.

    Short Code Snippet:

    gridExtra::grid.arrange(plot1, plot2, ncol = 2)
    
    0 讨论(0)
  • 2020-11-22 02:39

    You can use the following multiplot function from Winston Chang's R cookbook

    multiplot(plot1, plot2, cols=2)
    

    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 ))
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 02:39

    The above solutions may not be efficient if you want to plot multiple ggplot plots using a loop (e.g. as asked here: Creating multiple plots in ggplot with different Y-axis values using a loop), which is a desired step in analyzing the unknown (or large) data-sets (e.g., when you want to plot Counts of all variables in a data-set).

    The code below shows how to do that using the mentioned above 'multiplot()', the source of which is here: http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2):

    plotAllCounts <- function (dt){   
      plots <- list();
      for(i in 1:ncol(dt)) {
        strX = names(dt)[i]
        print(sprintf("%i: strX = %s", i, strX))
        plots[[i]] <- ggplot(dt) + xlab(strX) +
          geom_point(aes_string(strX),stat="count")
      }
    
      columnsToPlot <- floor(sqrt(ncol(dt)))
      multiplot(plotlist = plots, cols = columnsToPlot)
    }
    

    Now run the function - to get Counts for all variables printed using ggplot on one page

    dt = ggplot2::diamonds
    plotAllCounts(dt)
    

    One things to note is that:
    using aes(get(strX)), which you would normally use in loops when working with ggplot , in the above code instead of aes_string(strX) will NOT draw the desired plots. Instead, it will plot the last plot many times. I have not figured out why - it may have to do the aes and aes_string are called in ggplot.

    Otherwise, hope you'll find the function useful.

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