Search code examples
rggplot2plotfacet-gridggrepel

Make text labels span multiple ggplot facet grid panes


How can geom_text_repel() labels be made to span multiple facet_grid() panes? For instance, if there are many long labels that do not fit within the proper dimensions of each grid plot, the label should be positioned as if the facet_grid() were a single plot.

For example:

df <- data.frame(
  x = rep(1:3, 5), 
  y = runif(15), 
  label = paste0("very long label ", 1:15), 
  group = do.call(c, lapply(paste0("group ", 1:5), function(x) rep(x, 3)))
)

library(ggplot2)
library(ggrepel)
ggplot(df, aes(x, y, label = label)) + 
  geom_point() + 
  facet_grid(cols = vars(group)) + 
  geom_text_repel()

Example of how to not label across facet grids

If there is another way to group samples on the x-axis that would mimic a column-wise facet-grid, that's perfectly fine too. In my case, I need to group samples by a grouping variable (correspondingly labeled), and then within each group order them by a continuous variable.


Solution

  • Use clip = "off" from coord_cartesian:

    library(ggplot2)
    library(ggrepel)
    ggplot(df, aes(x, y, label = label)) + 
      geom_point() + 
      facet_grid(cols = vars(group)) + 
      geom_text_repel() + 
      coord_cartesian(clip = "off")
    

    enter image description here


    If this is not enough, one other option is to use multilining with stringr::str_wrap:

    library(stringr)
    library(dplyr)
    df %>% 
      mutate(label_wrapped = str_wrap(label, width = 20)) %>%
      ggplot(aes(x, y, label = label_wrapped)) + 
      geom_point() + 
      facet_grid(cols = vars(group)) + 
      geom_text_repel() + 
      coord_cartesian(clip = 'off')
    

    enter image description here


    data

    set.seed(2)
    df <- data.frame(
      x = rep(1:3, 5), 
      y = runif(15), 
      label = paste0("very very very long label ", 1:15),
      group = do.call(c, lapply(paste0("group ", 1:5), function(x) rep(x, 3)))
    )