How can I keep grid.arrange from cutting off x-axis labels on 4 panel plot in R?

Viewed 1318

I have 4 figures that I would like to make into a single plot. I can do so by making the figures in ggplot then converting them to grobs to use in grid.arrange. However, grid.arrange seems to cut off the x-axis labels of the bottom-left and bottom-right figures, which in this case should be dates. Any ideas on how to keep the grid.arrange from cutting off the x-axis labels of this 4-panel plot?

The final product should look like this, with the axes all aligned and with the same width and height. enter image description here

Reproducible Example:

library(ggplot2)
library(grid)
library(gridExtra)

df1 <- data.frame(matrix(ncol = 2, nrow = 7))
x <- c("Date", "Value")
colnames(df1) <- x
df1$Date <- seq(as.Date("2021-08-01"), as.Date("2021-08-07"), by = "day")
set.seed(321)
df1$Value <- rnorm(7,20,2)

df2 <- data.frame(matrix(ncol = 2, nrow = 7))
colnames(df2) <- x
df2$Date <- seq(as.Date("2021-08-01"), as.Date("2021-08-07"), by = "day")
df2$Value <- rnorm(7,19,2)

df3 <- data.frame(matrix(ncol = 2, nrow = 7))
colnames(df3) <- x
df3$Date <- seq(as.Date("2021-08-01"), as.Date("2021-08-07"), by = "day")
df3$Value <- rnorm(7,7,1)

df4 <- data.frame(matrix(ncol = 2, nrow = 7))
colnames(df4) <- x
df4$Date <- seq(as.Date("2021-08-01"), as.Date("2021-08-07"), by = "day")
df4$Value <- rnorm(7,10,3)

p1 <- ggplot(data = df1, aes(Date,Value)) +
  geom_line() +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_text(size = 16, color = "black"),
        legend.position = "none")
p2 <- ggplot(data = df2, aes(Date,Value)) +
  geom_line() +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.title.x = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_text(size = 16, color = "black"),
        legend.position = "none")
p3 <- ggplot(data = df3, aes(Date,Value)) +
  geom_line() +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.title.x = element_blank(),
        axis.text.x = element_text(size = 16, color = "black", angle = 30, vjust = 1, hjust = 1),
        axis.text.y = element_text(size = 16, color = "black"),
        legend.position = "none")
p4 <- ggplot(data = df4, aes(Date,Value)) +
  geom_line() +
  theme_bw() +
  theme(panel.grid = element_blank(),
        text = element_text(size = 16),
        axis.title.x = element_blank(),
        axis.text.x = element_text(size = 16, color = "black", angle = 30, vjust = 1, hjust = 1),
        axis.text.y = element_text(size = 16, color = "black"),
        legend.position = "none")

g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)
g3 <- ggplotGrob(p3)
g4 <- ggplotGrob(p4)

g2$widths <- g1$widths
g3$widths <- g1$widths
g4$widths <- g1$widths

g3$heights <- g1$heights
g4$heights <- g1$heights

grid.newpage()
grid.arrange(g1, g2, g3, g4, ncol = 2) #cuts off x-axes labels of g3 and g4
2 Answers

We could use plot_grid with align = 'hv' argument from cowplot package.

Update: (see comments OP):

plot_grid(p1, p2, p3, p4, ncol = 2, align = "hv")

enter image description here

First answer:

library(cowplot)
plot_grid(p1, p2, p3, p4, align = 'v')

enter image description here

Example of the patchwork package (assuming you've already ran the code in the question). As you can see, the top two plots are not wider than the bottom ones.

library(patchwork)
p1 + p2 + p3 + p4 + plot_layout(ncol = 2)

Created on 2021-08-05 by the reprex package (v1.0.0)

Related