2

I am making a multi-panel plot using ggplot2 and cowplot packages, but I need to change the height of a single plot. It is easiest shown with an example

library(ggplot2)
library(cowplot)

p1 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + 
             geom_point() +
             theme(axis.text.x = element_blank(),
                   axis.title.x = element_blank(),
                   legend.position = "none")
p2 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + 
             geom_point() +
             theme(axis.text.x = element_blank(),
                   axis.title.x = element_blank(),
                   axis.text.y = element_blank(),
                   axis.title.y = element_blank(),
                   legend.position = "none")
p3 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + 
             geom_point() +
             theme(axis.text.y = element_blank(),
                   axis.title.y = element_blank(),
                   legend.position = "none")
p4 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + 
             geom_point() + 
             theme(legend.position = "none")
p5 <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + 
             geom_point() +
             theme(axis.text.y = element_blank(),
                   axis.title.y = element_blank(),
                   legend.position = "none")

pL <- ggplot(iris, aes(Sepal.Width, Sepal.Length, colour = Species)) + geom_point()
l <- get_legend(pL)

# simple grid
plot_grid(p1, p2, p3, p4, p5, l, ncol = 3)

enter image description here

As you can see the y axis in the far right top panel has been shrunk in comparison with the two other panels in the same row by the inclusion of the x-axis title.

So how do I set the relative height and width of this single panel, so that the y-axis aligns with the y-axis of the panels in the top row?

You cannot set individual panels using rel_heights = and rel_widths() = arguments, and when I tried to add axis = "tblr" and align = "hv" arguments I got the error message

Error in `[.unit.list`(sizes[[x]], list_indices[[x]]) : 
  index out of bounds (unit list subsetting) 
llewmills
  • 2,959
  • 3
  • 31
  • 58
  • Is it strictly necessary to use `cowplot`? I think it might be easier to build that plot with a `facet_wrap` and then just use `theme(legend.position)` to move the legend from its default position. However, if it is a must to use `cowplot`, you could take a look at `ggdraw` and `draw_plot` functions. – Jonathan V. Solórzano Mar 27 '20 at 03:24

2 Answers2

5

patchwork package can get the job done. egg or multipanelfigure packages might work too.

# https://github.com/thomasp85/patchwork
# install.packages("devtools", dependencies = TRUE)
# devtools::install_github("thomasp85/patchwork")
library(patchwork)
#> 
#> Attaching package: 'patchwork'
#> The following object is masked from 'package:cowplot':
#> 
#>     align_plots

layout <- "
ABC
DEF
"
p1 + p2 + p3 + p4 + p5 + l +
  plot_layout(design = layout)

(p1 + p2 + p3)/(p4 + p5 + l) +
  plot_layout(nrow = 2) +
  plot_annotation(title = "Title",
                  subtitle = "Subtitle",
                  tag_levels = 'i',
                  tag_suffix = ')')

Created on 2020-03-26 by the reprex package (v0.3.0)

Tung
  • 26,371
  • 7
  • 91
  • 115
4

@Tung's answers were great, but I also worked out how to do it in cowplot. You simply create two separate panels, one for each row, then you can use the align= and axis= arguments to align the y-axis. We align the y-axis vertically based on the horizontal reference lines, so we specify align = "h".

top_row <- plot_grid(p1, p2, p3, align = "h", axis = "l", ncol = 3)

bottom_row <- plot_grid(p4, p5, l, align = "h", axis = "l", ncol = 3)

plot_grid(top_row, bottom_row, ncol = 1)

enter image description here

llewmills
  • 2,959
  • 3
  • 31
  • 58