Align plots after fixing panel size with ggh4x

66 views Asked by At

I have a series of multi-panel figures that I would like to have the same panel dimensions (i.e., plotting area). After searching for options on how to accomplish fixed panels, I settled on ggh4x because it retains the ggplot2 object type. However, when I add force_panelsizes() to my plot, the plots no longer align using plot_grid() from the cowplot library. As you'll see in the plot_grid() call, I would like these plots to align at the top of the graph and the x-axis, but I can't get it to work. I have include a reproducible example below:

library(ggplot2)
library(ggh4x)
library(cowplot)

a <- ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = class)) +
  theme(legend.position = "bottom") +
  force_panelsizes(rows = unit(3, "in"),
                   cols = unit(3, "in"))
 b <- ggplot(data = mpg) +
   geom_boxplot(aes(x = as.factor(cyl), y = hwy)) +
   force_panelsizes(rows = unit(3, "in"),
                    cols = unit(3, "in"))
 
 plot_grid(
   a,
   b,
   labels = c("A.", "B."),
   vjust = 3,
   #scale = 0.9,
   ncol = 2,
   align = 'h', axis = "bt"
 ) 
 
 ggsave(
   "repro.png",
   height = 6,
   width = 7.5,
   units = "in",
   dpi = 300
 )

The output ends up looking like this: enter image description here

2

There are 2 answers

0
Umar On

following your code, I used ggh4x to enforce fixed panel sizes and then align the plots using cowplot, you can manually set the size of the plots before using align_plots.

library(ggplot2)
library(ggh4x)
library(cowplot)

a <- ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = class)) +
  theme(legend.position = "bottom") +
  force_panelsizes(rows = unit(3, "in"),
                   cols = unit(3, "in"))

b <- ggplot(data = mpg) +
  geom_boxplot(aes(x = as.factor(cyl), y = hwy)) +
  force_panelsizes(rows = unit(3, "in"),
                   cols = unit(3, "in"))

# Set the size of each plot manually
a <- a + theme(plot.margin = margin(1, 1, 0, 0, "cm"))
b <- b + theme(plot.margin = margin(0, 0, 1, 1, "cm"))

# Align plots
aligned_plots <- align_plots(a, b, align = "v")
#aligned_plots <- align_patches(list(a, b), align = "v")#sometime align_plots gives erro in such case use 
plot_grid(
  aligned_plots[[1]],  # Access the first aligned plot
  aligned_plots[[2]],  # Access the second aligned plot
  labels = c("A.", "B."),
  vjust = 0,
  ncol = 2,
  align = 'h', axis = "bt"
)

ggsave(
  "repro.png",
  height = 6,
  width = 7.5,
  units = "in",
  dpi = 300
)

enter image description here

0
stefan On

This is a terrible hack. As the issue is related to the first plot having a guide while the second doesn't, one option would be to add a legend to the second plot too, but making it invisible.

To this end I added a geom_point to your b plot for which I map class on the color aes but otherwise set x and y to NA. This will add a color legend to the second plot. To make the legend invisible I first set color=NA for the legend using the override.aes argument of guide_legend. Second, I set the legend text, title and key to element_blank using theme options. Finally, as the second plot overlaps the first plot's legend I set the fill and color of the plot background for the second plot to NA.

library(ggplot2)
library(ggh4x)
library(cowplot)

b <- b +
  geom_point(
    aes(color = class),
    x = NA_real_, y = NA_real_, na.rm = TRUE
  ) +
  theme(
    legend.position = "bottom",
    plot.background = element_rect(fill = NA, color = NA),
    legend.key = element_blank(),
    legend.text = element_blank(),
    legend.title = element_blank()
  ) +
  guides(color = guide_legend(
    override.aes = list(color = NA)
  ))

plot_grid(
  a,
  b,
  labels = c("A.", "B."),
  vjust = 3,
  ncol = 2,
  align = "h", axis = "bt"
)

ggsave(
  "repro.png",
  height = 6,
  width = 7.5,
  units = "in",
  dpi = 300,
  bg = "white"
)

enter image description here