teunbrand / ggh4x

ggplot extension: options for tailored facets, multiple colourscales and miscellaneous
https://teunbrand.github.io/ggh4x/
Other
534 stars 32 forks source link

force_panelsizes and ggMarginal #119

Closed robinweide closed 6 months ago

robinweide commented 11 months ago

Again, thanks so much for this excellent package.

Background I want to create a fixed-size scatterplot, which includes density plots as marginals. Without the fixed-size, this is my reprex:

p <- ggplot(mtcars, aes(x = mpg, y = disp)) +
  geom_point()
p <- ggMarginal(p)
grid::grid.newpage()
grid::grid.draw(p)

image

Issue When I add force_panelsizes, it does a great job on the main panel. However, the marginals take over te rest of the available canvas.

p <- ggplot(mtcars, aes(x = mpg, y = disp)) +
  geom_point() +
  force_panelsizes(
    total_width = unit(42, "mm"),
    total_height = unit(42, "mm")
  )
p <- ggMarginal(p)
grid::grid.newpage()
grid::grid.draw(p)

image

Proposed solution I expect this is more of an issue of the ggExtra package, but I was hoping for a workaround within ggh4x nonetheless. A workaround I have been using is tweaking the chunk parameters fig.height and fig.width, but that forces all plots in the same chunk to abide by those dimensions. Preferably, one would set the chunk-parameters to be a big enough canvas, from which you can pull the smaller figure from within Illustrator or maybe even Plotgardener.

teunbrand commented 11 months ago

Hey Robin,

Because the ggMarginal() function returns a gtable class object, you should be able to manually set the widths/heights of the marginal plots. I've never used this function before, but the issue appears to be that they are 'null' units by defaults, which only makes sense in relation to other 'null' units in the same hierarchy of the plot. By setting an explicit panel size the 'null' unit that the panel usually takes to fit the window is gone and the marginal plots fill the leftover space.

library(ggh4x)
#> Loading required package: ggplot2
library(ggExtra)

p <- ggplot(mtcars, aes(x = mpg, y = disp)) +
  geom_point() +
  force_panelsizes(
    total_width = unit(42, "mm"),
    total_height = unit(42, "mm")
  )
p <- ggMarginal(p)

p$heights[1] <- unit(42 * 0.2, "mm")
p$widths[length(p$widths)] <- unit(42 * 0.2, "mm")
print(p)

Created on 2023-08-09 with reprex v2.0.2

Good luck!