Multiple points with same label in ggrepel – avoid redundant labels

I want to annotate a scatterplot with several points that have the same label. I want to label all of them (not just a part of them) but it is a mess with so many redundant labels.
Is there any way to have one single label pointing to all the points with the same label with ggrepel::geom_text_repel?

I attach the simplest possible situation:

df <- data.frame(
  group = c("A", "A", "B", "B"),
  x = c(1, 2, 3, 4),
  y = c(2, 3, 4, 5)
)
ggplot(df, aes(x, y)) +
  geom_point() +
  geom_text_repel(data=df, aes(label=group), box.padding = 0.5, force = 4)

Now:
enter image description here

What I want:
enter image description here

PS: @user2862862 posted the same question in 2019 but there was no proper answer in One label for multiple points

  • 5

    Instead of posting the same question again, I would rather put a bounty on the old one.

    – 

  • 5

    I get the feeling that solving this would lead to an even worse plot. It would be fine for your example, but once you have several points, it’s going to look incredibly messy. In general, I’m a fan of directly labelled plots, but where many points are labelled, it is often more elegant to use point color or shape to denote groupings. Could you give us a more realistic data sample? I can think of several possible solutions that might work here, but they are very dependent on the number of points.

    – 

  • 3

    This is interesting… I could imagine computing a summary data set with average x/y values for each group, then using geom_text_repel to label each group perhaps using blank labels for the actual points, and then extracting the text coords and going back to draw the lines…. it would take some doing.

    – 

  • 4

    @GregorThomas that was exactly my thought too, but it won’t work. The selective randomness in ggrepel is generated at draw time, with a makeContent mechanism on a bespoke grob. Neither a ggplot_build nor even a ggplot_gtable will contain the co-ordinates of the label – only the point from which the label is repelled. This is necessary because the labels need to repel appropriately when the plot is different sizes.

    – 

  • 1

    One option would be be to add the label and segments/arrows on separate plot layers. With precomputation this should work without using repulsion. I am not sure if it will work cleanly of not but package ‘ggpp’ provides function position_nudge_to() which could provide a different workaround. You can either force geom_text_repel() not to apply any repulsion, or you could use geom_text_s() from ‘ggpp’ which draws the segment based on nudging but does not apply any repulsion. Neither of these approaches uses repulsion, so both approaches need manual tweaking of the locations of the labels.

    – 

Leave a Comment