tidyverse / ggplot2

An implementation of the Grammar of Graphics in R
https://ggplot2.tidyverse.org
Other
6.5k stars 2.02k forks source link

Panel-based sizing of figures #5338

Open tfjaeger opened 1 year ago

tfjaeger commented 1 year ago

(Apologies if this has been raised and addressed before)

Despite all the marvels of ggplot2 and the many amazing extension packages, one thing that continues to consume a lot of time (or often is difficult to achieve at all) is the consistent sizing of figures for a publication. Specifically, I find that almost all the time my focus is on the relative sizing of panels (rather than the entire area of a figure) across figures. A common scenario is, for example, that I have the same multi-panel result plots across multiple figures. Another common scenario is that I'd like to plot a panel in Figure 1 at twice the width of Figure 2, etc. Critically, in all of these situations, my focus is on the panels rather than the entire figure.

I've searched across packages but I haven't found any easy way to create alignment in panel sizes across plots (I'd love to hear that I'm wrong!). Would it be possible, for example, to allow ggsave to save figures based on the panel size, or to provide other ways to easily express the dimensions of the panel itself. At the core of the issue that I'm trying to describe is that sizing seems to start by sizing the overall figure. The rest follows from that (incl. the panel size). But perhaps many researchers would find it more intuitive if sizing started with the panel? (plotting figures at 100% would then guarantee that all panels have proportional sizes as intended by the author).

Sorry, if this is all already solved or known to be unsolvable. In any case, thank you for all the amazing work on ggplot!!!

teunbrand commented 1 year ago

Back in the early days of ggplot2 (in 2011 or so), facets had widths and heights arguments to control the sizes of panels.

https://github.com/tidyverse/ggplot2/blob/77b060bf48afc6b0a92e1882262c39b3f2e3ec3b/R/facet-grid-.r#L83-L86

These had then been dropped and never re-introduced, see discussion at #566.

The current approaches for sizing panels can be using plot composition in {patchwork}, which aligns the plots based on the panels (but they have to be separate plots):

library(ggplot2)
library(patchwork)
library(ggforce)

p <- ggplot(mtcars, aes(disp, mpg)) +
  geom_point()

(p + facet_wrap_paginate(~  cyl, page = 1, ncol = 1, nrow = 1)) +
  (p + facet_wrap_paginate(~  cyl, page = 2, ncol = 1, nrow = 1)) +
  (p + facet_wrap_paginate(~  cyl, page = 3, ncol = 1, nrow = 1)) +
  plot_layout(widths = c(1, 1.5, 2), heights = 1)

If this you're looking to finetune panels in facets, you might also find ggh4x::force_panelsizes() useful, which can use relative sizes:

p + facet_wrap(~ cyl) +
  ggh4x::force_panelsizes(cols = c(1,1.5,2), rows = 1, respect = TRUE)

Or absolute sizes, which is more useful when you have to compose >1 plot:

p + facet_wrap(~ cyl) +
  ggh4x::force_panelsizes(cols = unit(c(2,3,4), "cm"), rows = unit(2, "cm"))

Created on 2023-06-27 with reprex v2.0.2

In the bioconductor ecosystem there is also {plotgardener} that does some plot composition based on absolute sizes.

I'd love ggplot2 to have some more flexible options with regards to panel sizes, but given that it has been rejected before, I'm curious if the maintainers' thoughts have evolved since then.

tfjaeger commented 1 year ago

Thank you for all the pointers, Teun! I will explore ggh4x a bit more to see whether that can address our needs. And, like you, I'm curious to hear whether the ggplot2 maintainers have any thoughts on this.

teunbrand commented 1 year ago

@thomasp85 do you have any thoughts on this? I think it would be useful, but I can imagine it would be a nightmare for patchwork :)

thomasp85 commented 1 year ago

Patchwork already has functionality to align plots so that they all share the same size. This makes it possible to eg have the same panel location throughout a slideshow or, as the op asks, to ensure the same sizing in a publication

teunbrand commented 10 months ago

If this functionality exists in patchwork, it is probably redudant to implement this in ggplot2 as well.

teunbrand commented 1 month ago

I'm going to resurrect this due to some discussion with Thomas off-github

tfjaeger commented 1 month ago

Fwiw, I have been using patchwork and have not found that it solves the issue of consistent sizing across different plots (e.g., consistently having the same physical panel size across different types of plots: e.g., both for a single panel and a 3x3 panel plot). But perhaps I just haven't figure out that part yet. I did have success with ggh4x, as suggested by @teunbrand. But it'd be lovely if there was a more automatic way to set a few constants at the top of an R script/Rmd and then have consistent sizing across the entire paper.

(But perhaps I'm really misssing something fundamental, and it's much easier than I think; anyway, thanks for reopening this issue.)