Home > Software design >  custom labels beside a 1-column grid of plots, in R
custom labels beside a 1-column grid of plots, in R

Time:02-25

Given a number (4) of ggplot objects of equal dimensions, when combining them into a figure as 1 column of plots, I would like custom text on left beside each plot. Combining the plots is easy with help of packages such as cowplot, ggarrange, patchwork - and adding a tag letter e.g. 'A' 'B' beside each is easy. But adding a longer text on left side of each plot is difficult.

First I tried using Patchwork, with tag_suffix as below but it shows only first tag for all four plots:

(substituted generic plots below)

library(patchwork)
var_titles <- c('Study Design',
'Type of data',
'Source of data',
'Internal validity rating')
p1 <- ggplot(mtcars)   geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars)   geom_boxplot(aes(gear, disp, group = gear))
p3 <- ggplot(mtcars)   geom_point(aes(mpg, disp))
p4 <- ggplot(mtcars)   geom_boxplot(aes(gear, disp, group = gear))
p1   p2   p3   p4  
plot_layout(nrow = 4)  
plot_annotation(tag_levels = '1', tag_suffix = var_titles)

Then I tried in Cowplot, and by inserting an extra column on left with NULL blank plot, it made space on left for my labels, but positioning is hard and linebreaks \n inside strings fail.

library(cowplot)
var_titles <- c('Study Design', 
                'Type of data', 
                'Source of data', 
                'Internal validity rating')
row_1 <- plot_grid(NULL, p1,
                   nrow=1, ncol=2,
                   rel_widths = c(543/3543, 3000/3543),
                   labels = var_titles[1],
                   label_x = c(-0.3),
                   label_y = c(0.6))
row_2 <- plot_grid(NULL, p2,
                   nrow=1, ncol=2,
                   rel_widths = c(543/3543, 3000/3543),
                   labels = var_titles[2],
                   label_x = c(-0.3),
                   label_y = c(0.6))
row_3 <- plot_grid(NULL, p3,
                   nrow=1, ncol=2,
                   rel_widths = c(543/3543, 3000/3543),
                   labels = var_titles[3],
                   label_x = c(-0.4),
                   label_y = c(0.6))
row_4 <- plot_grid(NULL, p4,
                   nrow=1, ncol=2,
                   rel_widths = c(543/3543, 3000/3543),
                   labels = var_titles[4],
                   label_x = c(0),
                   label_y = c(0.5))

thisPlot <- plot_grid(row_1, row_2, row_3, row_4,
                      nrow = 4,
                      rel_heights = c(7/29, 7/29, 7/29, 8/29))
thisPlot

The actual plots are single horizontally stacked bars, each for a different variable showing proportions (a different set of categories for each variable, and that's why I first plotted them separately, rather than just making a set of stacked bars).

Please any suggestions of another way to do this - I have also tried ggarrange but not yet gridExtra's grid.arrange

Screenshots are (1) quick-fake version to show what the combined plot is aiming for, tags would be in blank space on left side; (2) what I get with patchwork so far; (3) leftmost edge of Cowplot result, which is nearly there but so fiddly - whereas I imagined there would be a common desire to put a text description next to each of a set of plots?

mockup of aim for Figure Patchwork tag repeats first label only only left edge of Cowplot, labels there but need to break on to 2 or 3 lines

CodePudding user response:

I would handle this by creating completely blank plots with only text and adding these to your patchwork design. A little function makes the code less repetetive:

label_plot <- function(label) {
  ggplot()   
    geom_text(aes(x = 0, y = 0, label = label), size = 6, fontface = 2)   
    theme_void()
}

So now you can do:

 label_plot("1 Study\nDesign")   p1  
 label_plot("2 Study\nDesign")   p2   
 label_plot("3 Study\nDesign")   p3  
 label_plot("4 Study\nDesign")   p4  
 plot_layout(nrow = 4, widths = c(1, 4))

enter image description here

Of course, you are completely free to change the size, color, font, positioning of the text for each label, since each one is itself a complete ggplot object.

  • Related