Search code examples
rggplot2ggrepel

Place labels above and below interspersed


I am using ggrepel to add labels to my ggplot graph. To better use the space in the plot I want to add one label above an "upper_value" and the following below the "bottom_value" along the x-axis, interspersed.

The problem is that the bottom labels keep showing up next to the upper labels, even when I set nudge_y accordingly.

Here's what I've tried:

set.seed(5)

library(ggplot2)
library(ggrepel)
library(dplyr)

d <- data.frame(
  x = 1:60,
  y = c(
    sample(x = seq(0,0.2,0.01), size = 20, replace = TRUE),
    sample(x = seq(0.8,1,0.01), size = 20, replace = TRUE),
    sample(x = seq(0,0.2,0.01), size = 20, replace = TRUE)
  )
) 

# add labels for high scores
d$labs[d$y >= 0.8] <- paste0("label_",letters[1:20])
    
# add a column to intersperse labels (above=1 and below=2)
d_lab <- d %>% 
  filter(!is.na(labs) ) %>% 
  mutate(lab_set = rep(c(1,2), nrow(.)/2) )

ggplot(data = d, aes(x = x, y = y), show.legend = TRUE) +
  geom_line() + 
  geom_point(data =  filter(d, !is.na(labs)), color = "red") +
  # place labels above 1.2
  geom_label_repel(
    data =  filter(d_lab, lab_set == "1"),aes(label = labs),
    segment.color = "black", 
    arrow = arrow(length = unit(0.01, "npc"), type = "closed", ends = "first"),
    fill = alpha(c("white"),0.5),
    #show.legend = FALSE,
    color = "black",
    direction = "x",
    nudge_y = 1.2
  ) +
  # place labels below 0.8 --> does not respond to nudge_y!!!
  geom_label_repel(
    data =  filter(d_lab, lab_set == "2"),aes(label = labs),
    segment.color = "black", 
    arrow = arrow(length = unit(0.01, "npc"), type = "closed", ends = "first"),
    fill = alpha(c("white"),0.5),
    #show.legend = FALSE,
    color = "black",
    direction = "x",
    nudge_y = 0.8
  ) +
  scale_y_continuous(limits = c(NA, 1.2))   

Solution

  • Try using a negative value for nudge_y in the second geom_label_repel call to nudge downward:

    ggplot(data = d, aes(x = x, y = y), show.legend = TRUE) +
      geom_line() + 
      geom_point(data =  filter(d, !is.na(labs)), color = "red") +
      # place labels above 1.2
      geom_label_repel(
        data =  filter(d_lab, lab_set == "1"),aes(label = labs),
        segment.color = "black", 
        arrow = arrow(length = unit(0.01, "npc"), type = "closed", ends = "first"),
        fill = alpha(c("white"),0.5),
        #show.legend = FALSE,
        color = "black",
        direction = "x",
        nudge_y = 1.2
      ) +
      # place labels below 0.8 --> does not respond to nudge_y!!!
      geom_label_repel(
        data =  filter(d_lab, lab_set == "2"),aes(label = labs),
        segment.color = "black", 
        arrow = arrow(length = unit(0.01, "npc"), type = "closed", ends = "first"),
        fill = alpha(c("white"),0.5),
        #show.legend = FALSE,
        color = "black",
        direction = "x",
        nudge_y = -0.25 # USE NEGATIVE VALUE HERE
      ) +
      scale_y_continuous(limits = c(NA, 1.2))