rggplot2cowplotgrobpatchwork

Properly size multiple ggExtraPlot objects after calling ggMarginal in R


I want to create a facet-like effect with ggExtra::ggMarginal plots. This is not yet directly possible, so I tried to use patchwork::wrap_plots, cowplot::plot_grid, and egg::ggarrange to do it myself. I have everything properly developed—except for the plot sizing. patchwork and egg make the panels of ggplot objects the same size, but this behavior does not apply to the ggExtraPlot objects that ggMarginal creates.

For example, consider the following patchwork of ggplots (code below): four ggplots correctly sized

But once I add the marginal densities, the arrangement looks like this: four ggplots incorrectly sized

As you can see, the panels of each plot are no longer equally sized; rather, the entire objects are. I want the panel sizes of each ggplot in the second plot to be the same, as in the first plot.

Attempted solutions:

I would appreciate advice on guaranteeing equal panel sizes for the four plots, ideally without relying on the actual size (i.e., in pixels) of the components. It would be awesome to see ggMarginal allow faceting and to see patchwork extend beyond simple ggplot objects!

b <- ggplot(mtcars, aes(x = disp, y = mpg)) +
  geom_point() +
  labs(x = "some\nlines",
       y = "many\nnew\nlines")

p1 <-  b +
  theme(axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        axis.ticks.x = element_blank())
p1m <- ggExtra::ggMarginal(p1, margins = "y")

p2 <- b +
  theme(axis.title = element_blank(),
        axis.text = element_blank(),
        axis.ticks = element_blank())
p2m <- ggExtra::ggMarginal(p2, margins = "y")

p3 <- b
p3m <- ggExtra::ggMarginal(p3, margins = "y")

p4 <- b +
  theme(axis.title.y = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks.y = element_blank())
p4m <- ggExtra::ggMarginal(p4, margins = "y")

patchwork::wrap_plots(p1, p2, p3, p4, nrow = 2)      # this looks great!
patchwork::wrap_plots(p1m, p2m, p3m, p4m, nrow = 2)  # this doesn't :(

Solution

  • Instead of relying on ggMarginal one option would be to manually create your density plots and glue both your main and the density plots together using patchwork:

    library(ggplot2)
    library(patchwork)
    
    dp <- ggplot(mtcars, aes(y = mpg)) +
      geom_density() +
      theme_void()
    
    list(p1, dp, p2, dp, p3, dp, p4, dp) |> 
      wrap_plots(nrow = 2, widths = c(5, 1, 5, 1))