aligning distinct non-facet plots in ggplot2 using Rpy2 in Python

前端 未结 3 1453
广开言路
广开言路 2021-01-02 01:55

I am combining two distinct plots into a grid layout with grid as suggested by @lgautier in rpy2 using python. The top plot is a density and and the bottom a ba

3条回答
  •  说谎
    说谎 (楼主)
    2021-01-02 02:14

    Aligning two plots becomes much trickier when facets are involved. I don't know if there is a general solution, even in R. Consider this scenario,

    p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() + 
      facet_wrap(~ cyl, ncol=2,scales="free")
    p2 <- p1 + facet_null() + aes(colour=am) + ylab("this\nis taller")
    
    gridExtra::grid.arrange(p1, p2)
    

    enter image description here

    With some work, you can compare the widths for the left axis, and the legends (which may or may not be present on the right side).

    library(gtable)
    
    # legend, if it exists, may be the second last item on the right, 
    # unless it's not on the right side.
    locate_guide <- function(g){
      right <- max(g$layout$r)
      gg <- subset(g$layout, (grepl("guide", g$layout$name) & r == right - 1L) | 
                     r == right)
      sort(gg$r)
    }
    
    compare_left <- function(g1, g2){
    
      w1 <- g1$widths[1:3]
      w2 <- g2$widths[1:3]
      unit.pmax(w1, w2)
    }
    
    align_lr <- function(g1, g2){
    
      # align the left side 
      left <- compare_left(g1, g2)
      g1$widths[1:3] <- g2$widths[1:3] <- left
    
      # now deal with the right side
    
      gl1 <- locate_guide(g1)
      gl2 <- locate_guide(g2)
    
      if(length(gl1) < length(gl2)){
        g1$widths[[gl1]] <- max(g1$widths[gl1], g2$widths[gl2[2]]) +
          g2$widths[gl2[1]]
      }
      if(length(gl2) < length(gl1)){
        g2$widths[[gl2]] <- max(g2$widths[gl2], g1$widths[gl1[2]]) +
          g1$widths[gl1[1]]
      }
      if(length(gl1) == length(gl2)){
        g1$widths[[gl1]] <-  g2$widths[[gl2]] <- unit.pmax(g1$widths[gl1], g2$widths[gl2])
      }
    
      grid.arrange(g1, g2)
    }
    
    align_lr(g1, g2)
    

    enter image description here

    Note that I haven't tested other cases; I'm sure it's very easy to break. As far as I understand from the docs, rpy2 provides a mechanism to use an arbitrary piece of R code, so the conversion should not be a problem.

提交回复
热议问题