6

I have ran into an issue with combining plots using patchwork when theme(aspect.ratio = 1). Provided are a a few examples:

library(tidyverse)
library(patchwork)

# Create the base plots
plotlist = list(
  fig1 = iris %>% 
    filter(Species == "setosa") %>% 
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point(),
  
  fig2 = iris %>% 
    filter(Species == "versicolor") %>% 
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point(),
  
  fig3 = iris %>% 
    filter(Species == "virginica") %>% 
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
    geom_point()
)

# Here patchwork combines the plots nicely
plotlist$fig1 / (plotlist$fig2 + plotlist$fig3)


# However, if we change the aspect.ratio to 1 things don't look so nice anymore
plotlist = lapply(plotlist, function(x) {
  x + theme(aspect.ratio = 1)
})

# Notice the large gap between plots. Instead, I would like the plots in the second row to be almost directly under the first row.
plotlist$fig1 / (plotlist$fig2 + plotlist$fig3)

# I tried setting the margins to zero, but that doesn't change anything
plotlist = lapply(plotlist, function(x) {
  x + theme(plot.margin = margin(0, 0, 0, 0, unit = "pt"))
})

plotlist$fig1 / (plotlist$fig2 + plotlist$fig3)

How can I improve the layout using patchwork? The plots in the second row should have half the width of the first row, like the first plot, but the aspect ratio should be 1 for all plots.

mhovd
  • 3,724
  • 2
  • 21
  • 47
  • How about `plotlist$fig1 / (plotlist$fig2 + plotlist$fig3) + plot_layout(widths = 1)` – phiver Jul 14 '21 at 11:17
  • That's a good suggestion! While that did resolve the issue with spacing, it did not produce the layout I wanted (plots in the second row should be limited to the width of the first row). Using `widths = c(1,2)` did not resolve that either. – mhovd Jul 14 '21 at 11:34
  • Difficult to get correct. This gets it closer. `design <- "#1# #23" plotlist$fig1 / (plotlist$fig2 + plotlist$fig3) + plot_layout(design = design, widths = c(1,2))` . btw, design should be on 2 codelines. Copy paste out of a comment doesn't work very well. – phiver Jul 14 '21 at 11:42
  • Unfortunately, that didn't work as expected, and neither did `design <- c(area(1, 1), area(2, 3))`. Without the aspect ratio your suggestion works, but when `aspect.ratio = 1` it fails to produce the desired layout. – mhovd Jul 15 '21 at 07:30
  • You can read more about it on patchwork package docs: https://patchwork.data-imaginist.com/articles/guides/layout.html#fixed-aspect-plots – Bruno Mioto Nov 30 '22 at 04:01

1 Answers1

5

I have also struggled a lot with figures that have aspect ratios using patchwork.

First I give you the solution and below I give you a bit more explanation on why I think this code reproduces the correct figure.

Solution:

design <- "
  33
  12
    "
plotlist$fig2 + plotlist$fig3 + plotlist$fig1 + 
    plot_layout(
        design = design, 
        heights = unit(c(2,-1),c("null","null"))
  )

enter image description here


Extra Info:

One key insight that I had is that one can specify -1 NULL units in the height and width arguments which specifies that columns and rows with such a unit should adapt to the dimensions of figures with a fixed aspect ratio (I think...).

For example in the code below I give you an example where I have a figure with an aspect ratio of 1 that I want to preserve, but I want to be able to specify the widths of the other columns. Here I specified that the middle column should have 3cm width (at least when I took the screenshot) the right column should respect the aspect ratio of the figure (eg. -1 NULLunit) and the left column can fill the remaining space (eg. 1 NULL unit).

library(ggplot2)
library(patchwork)
p1 <- ggplot(mtcars) + geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) + geom_boxplot(aes(gear, disp, group = gear)) + theme(aspect.ratio = 1)
p1 + p1 + p2 + plot_layout(widths = unit(c(1,3,-1), c("null","cm","null")))

enter image description here

Edit: as of patchwork version 1.1.3 this behavior is now also officially documented in the vignette: https://patchwork.data-imaginist.com/articles/guides/layout.html#fixed-aspect-plots

Thus to produce your figure, I specify that the last row should respect the aspect ratio of the figures while specifying that the first row should be twice the height.

Escalen
  • 156
  • 7