How to perfectly align an unequal number of plots (ggplot2,gridExtra)

后端 未结 2 1373
北恋
北恋 2021-02-04 11:34

I would like to perfectly align these plots :

Here is the R code :

library(tidyverse)
library(gridExtra)
groupes <- tribble(~type, ~group, ~p         


        
相关标签:
2条回答
  • 2021-02-04 12:08

    Thanks to @user9471246 I managed to create a working solution. The main problem was solved by @user9471246 and then a secondary problem emerged : the height of the "panel-strip" changed as a function of the height of the characters (for example, if the panel title is "aaa" the panel-strip will be shorter than is the panel title is "Égo", because the panel-strips are drawn independently from each other). My solution is to get rid of the panel-strip and to move the panel title into the plot.

    library(tidyverse)
    library(gridExtra)
    library(grid)
    # it also requires the "egg" package
    groupes <- tribble(~type, ~group, ~prof, ~var,
                       1,"Aa",1,12,
                       1,"Aa",2,-24,
                       1,"Bb",1,-11,
                       1,"Bb",2,7,
                       1,"Cc",1,12,
                       1,"Cc",2,-5,
                       2,"Ég",1,10,
                       2,"Ég",2,5,
                       2,"Yg",1,-25,
                       2,"Yg",2,2,
                       2,"Ab",1,10,
                       2,"Ab",2,3,
                       2,"Cc",1,8,
                       2,"Cc",2,25,
                       3,"Dd",1,10,
                       3,"Dd",2,-5,
                       3,"Ee",1,25,
                       3,"Ee",2,2,
                       3,"Ff",1,-10,
                       3,"Ff",2,3,
                       3,"Ii",1,25,
                       3,"Ii",2,-18,
                       3,"Ll",1,20,
                       3,"Ll",2,-20)
    
    
    dat_text <- groupes %>% distinct(type, group)
    
    
    
    p1 <-  groupes %>% filter(type==1) %>% ggplot(aes(prof,var)) + geom_col() + facet_wrap(~group,ncol=1) +
      coord_cartesian(ylim=c(-25,25)) +
      geom_text(data=filter(dat_text,type==1), aes(x = Inf, y = Inf, label=group), hjust = 1, vjust = 1.05) +
      labs(title="type 1",x="",y="") +
      theme(strip.text.x = element_blank())
    p2 <-  groupes %>% filter(type==2) %>% ggplot(aes(prof,var)) + geom_col() + facet_wrap(~group,ncol=1) +
      coord_cartesian(ylim=c(-25,25)) +
      geom_text(data=filter(dat_text,type==2), aes(x = Inf, y = Inf, label=group), hjust = 1, vjust = 1.05) +
      labs(title="type 2",x="",y="") +
      theme(strip.text.x = element_blank())
    p3 <-  groupes %>% filter(type==3) %>% ggplot(aes(prof,var)) + geom_col() + facet_wrap(~group,ncol=1) +
      coord_cartesian(ylim=c(-25,25)) +
      geom_text(data=filter(dat_text,type==3), aes(x = Inf, y = Inf, label=group), hjust = 1, vjust = 1.05) +
      labs(title="type 3",x="",y="") +
      theme(strip.text.x = element_blank())
    
    
    
    justify <- function(x, hjust="center", vjust="center"){
      w <- sum(x$widths)
      h <- sum(x$heights)
      xj <- switch(hjust,
                   center = 0.5,
                   left = 0.5*w,
                   right=unit(1,"npc") - 0.5*w)
      yj <- switch(vjust,
                   center = 0.5,
                   bottom = 0.5*h,
                   top=unit(1,"npc") - 0.5*h)
      x$vp <- viewport(x=xj, y=yj)
      return(x)
    }
    
    
    gl <- lapply(list(p1,p2,p3),egg::set_panel_size, height=unit(1.95,"in"), width=unit(2.15,"in"))
    gl <- lapply(gl, justify, vjust="top")
    
    gridExtra::grid.arrange(grobs=gl, nrow=1)
    
    0 讨论(0)
  • 2021-02-04 12:10

    it's probably more manageable if you can set an absolute panel size (and size the device accordingly).

    justify <- function(x, hjust="center", vjust="center"){
      w <- sum(x$widths)
      h <- sum(x$heights)
      xj <- switch(hjust,
                   center = 0.5,
                   left = 0.5*w,
                   right=unit(1,"npc") - 0.5*w)
      yj <- switch(vjust,
                   center = 0.5,
                   bottom = 0.5*h,
                   top=unit(1,"npc") - 0.5*h)
      x$vp <- viewport(x=xj, y=yj)
      return(x)
    }
    
    library(grid)
    gl <- lapply(list(p1,p2,p3),egg::set_panel_size, height=unit(1,"in"))
    gl <- lapply(gl, justify, vjust="top")
    gridExtra::grid.arrange(grobs=gl, nrow=1)
    

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