Search code examples
rggplot2ggrepel

Labeling faceted plot with ggrepel and jittered dots


I am trying to plot three boxplots and label always the 2 highest values.

I tried creating a position element and use this to get same position for points and labels, but somehow this does not work.

set.seed(1)
df <- 
  data.frame(a=rep(letters, 3),
             b=LETTERS[1:3],
             int=runif(78, 15, 30))
jitter_pos <- position_jitter(width=.4, seed = 1)
ggplot(df,
       aes(1, int,
           color=b)) +
  geom_point(position=jitter_pos) +
  geom_boxplot(alpha=.3, outlier.shape=NA, fill=NA, color='#993404') +
  facet_wrap(~ b) +
  guides(color=FALSE) +
  geom_label_repel(data=df %>%
                     group_by(b) %>%
                     arrange(desc(int)) %>%
                     slice(1:2),
                   aes(label=a),
                   size=2.5, color='black',
                   fill='#FFFFFF33',
                   box.padding=1,
                   position=jitter_pos)

I am pretty sure it is just a little mistake but somehow I can't find my error. The labels do not match the dot positions.

Maybe a better solution would be with b on the x axis and using jitterdodge somehow, but this didn't worked ether, so I tried to get it running with facets. So nothing works for me yet.


Solution

  • Your mistake is in position_jitter's behavior and the issue is discussed at length in this github issue.

    The solution suggested by the ggrepel author is to add an explicit label column to the dataframe, with empty strings for the rows you want to omit:

    library(ggplot2)
    library(ggrepel)
    library(tidyverse)
    set.seed(1)
    df <- 
      data.frame(a=rep(letters, 3),
                 b=LETTERS[1:3],
                 int=runif(78, 15, 30)) %>%
      group_by(b) %>%
      mutate(label = if_else(rank(-int) %in% 1:2, as.character(a), ""))
    jitter_pos <- position_jitter(width=.4, height = 0, seed = 1)
    
    
    
    ggplot(df,
           aes(1, int,
               color=b)) +
      geom_jitter(position=jitter_pos) +
      geom_boxplot(alpha=.3, outlier.shape=NA, fill=NA, color='#993404') +
      guides(color=FALSE) +
      facet_wrap(~ b) +
      geom_label_repel(aes(x=1, y=int, label=label),
                       size=2.5, color='black',
                       fill='#FFFFFF33',
                       box.padding=1,
                       position=jitter_pos)
    

    Created on 2020-09-01 by the reprex package (v0.3.0)