Fixing plot area width when using layout_matrix in grid.arrange

孤街醉人 提交于 2019-12-12 12:41:04

问题


I am combining facet plots of tiles. I want each tile to be square, or at least take the same height and width.

So far I have managed to give equal height to each row of tiles using layout_matrix. I am stuck when trying to fix an equal width to each column of tiles (across the plots).

Some code based on mtcars to try and illustrate the layout of my plot (actual data way more complicated):

library("tidyverse")
library("gridExtra")

df0 <- mtcars %>% 
  group_by(cyl) %>%
  count()

df1 <- mtcars %>% 
  rownames_to_column("car") %>%
  mutate(man = gsub("([A-Za-z]+).*", "\\1", car))

g <- list()
for(i in 1:nrow(df0)){
  g[[i]] <- ggplot(data  =  df1 %>% filter(cyl == df0$cyl[i]), 
                   mapping = aes(x = "", y = car, fill = qsec)) +
    geom_tile() +
    facet_grid( man ~ .,  scales = "free_y", space = "free") +
    labs(x = "", y = "") +
    guides(fill = FALSE) +
    theme(strip.text.y = element_text(angle=0)) +
    coord_fixed()
}

m0 <- cbind(c(rep(1, df0$n[1]), rep(NA, max(df0$n) - df0$n[1])),
            c(rep(2, df0$n[2]), rep(NA, max(df0$n) - df0$n[2])),
            c(rep(3, df0$n[3]), rep(NA, max(df0$n) - df0$n[3])))
grid.arrange(grobs = g, layout_matrix =  m0)

Which produces this plot (minus my MS Paint skills):

Presumably the different lengths of the labels in the strip text and y axis lead to the different widths for the plotting area. Not sure how I can avoid this behavior though? I thought I could create on big facet_grid but I could not get anywhere near the layout of the plot above.


回答1:


Turns out this is a rather tricky thing to do. Luckily, cowplot::plot_grid can already do the alignment that results in equal sizes of the columns. I just took that function and removed the fluff, and decoupled the heights from the grid pattern it normally uses. We end up with a little custom function that does the job (all credits to Claus Wilke):

plot_grid_gjabel <- function(plots, heights) {
  grobs <- lapply(plots, function(x) {
    if (!is.null(x)) 
      cowplot:::ggplot_to_gtable(x)
    else NULL
  })
  num_plots <- length(plots)
  num_widths <- unique(lapply(grobs, function(x) {
    length(x$widths)
  }))
  num_widths[num_widths == 0] <- NULL
  max_widths <- do.call(grid::unit.pmax, 
                        lapply(grobs, function(x) { x$widths }))
  for (i in 1:num_plots) {
    grobs[[i]]$widths <- max_widths
  }
  width <- 1 / num_plots
  height <- heights / max(heights)
  x <- cumsum(width[rep(1, num_plots)]) - width
  p <- cowplot::ggdraw() 
  for (i in seq_along(plots)) {
    p <- p + cowplot::draw_grob(grid::grobTree(grobs[[i]]), x[i], 1 - height[i], 
                                width, height[i])
  }
  return(p)
}

We can simply call this like so:

plot_grid_gjabel(g, df0$n)

Resulting in:



来源:https://stackoverflow.com/questions/39717481/fixing-plot-area-width-when-using-layout-matrix-in-grid-arrange

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!