I see two options:
Insert empty plot
We can apply the insert_xaxis_grob()
/ insert_yaxis_grob()
functions iteratively to insert multiple grobs, one of which can be empty. In this way, we can insert a specified amount of space on either side of the marginal plots. Here I'm showing how to do this on the inside, to generate a gap between the main panel and the marginal plots:
# pmain, xbox, ybox are defined as in the question
pnull <- ggdraw() # generate empty plot
p1 <- insert_xaxis_grob(
insert_xaxis_grob(pmain, xbox, grid::unit(0.6, "in"), position = "top"),
pnull, grid::unit(0.2, "in"), position = "top")
p2 <- insert_yaxis_grob(
insert_yaxis_grob(p1, ybox, grid::unit(0.6, "in"), position = "right"),
pnull, grid::unit(0.2, "in"), position = "right")
ggdraw(p2)
Create gap in the marginal plots
Alternatively, since the marginal plots are drawn with ggplot2, we can just specify axis limits that generate space in the appropriate location. I.e., instead of xbox
and ybox
in the original code, we define xbox2
and ybox2
via:
xbox2 <- axis_canvas(pmain, axis = "x", coord_flip = TRUE) +
geom_boxplot(data = mpg, aes(y = cty, x = as.numeric(factor(cyl)), color = factor(cyl))) +
scale_x_continuous(limits = c(-2, 4.5)) + coord_flip()
ybox2 <- axis_canvas(pmain, axis = "y") +
geom_boxplot(data = mpg, aes(y = hwy, x = as.numeric(factor(cyl)), color = factor(cyl))) +
scale_x_continuous(limits = c(-2, 4.5))
p1 <- insert_xaxis_grob(pmain, xbox2, grid::unit(0.8, "in"), position = "top")
p2 <- insert_yaxis_grob(p1, ybox2, grid::unit(0.8, "in"), position = "right")
ggdraw(p2)
To understand what is happening here, let's compare xbox
and xbox2
side by side:
plot_grid(xbox + panel_border("black"),
xbox2 + panel_border("black"), nrow = 1, scale = 0.9)
We see how xbox2
(on the right) has extra space at the bottom, which was created by starting the axis at -2, even though the first box plot is located at position 1. More information on how to choose the axis ranges for these marginal plots can be found here.