Why is geom_text() plotting the text several times?
Asked Answered
R

2

10

Please consider the following minimal example:

library(ggplot2)
library(ggrepel)
ggplot(mtcars) +
  aes(x = mpg, y = qsec) +
  geom_line() +
  geom_text(x = 20, y = 20, label = "(20,20)")

overplotted text

I guess you can see pretty easily that the text "(20,20)" is heavily overplotted (actually, I don't know whether that's the correct word. I mean that the text is plotted several times at one location).

If I use annotate(), this does not happen:

ggplot(mtcars) +
  aes(x = mpg, y = qsec) +
  geom_line() +
  annotate("text", x = 20, y = 20, label = "(20,20)")

no overplotted text

"So, why don't you use annotate() then?" you might ask. Actually, I don't want to use text for annotation but labels. And I also want to use the {ggrepel} package to avoid overplotting. But look what happens, when I try this:

ggplot(mtcars) +
  aes(x = mpg, y = qsec) +
  geom_line() +
  geom_label_repel(x = 20, y = 20, label = "(20,20)")

many many labels

Again, many labels are plotted and {ggrepel} does a good job at preventing them from overlapping. But I want only one label pointing at a specific location. I really don't understand why this happens. I only supplied one value for x, y and label each. I also tried data = NULL and inherit.aes = F and putting the values into aes() within geom_label_repel() to no effect. I suspect that there are as many labels as there are rows in mtcars. For my real application that's really bad because I have a lot of rows in the respective dataset.

Could you help me out here and maybe give a short explanation why this happens and why your solution works? Thanks a lot!

Rodeo answered 27/2, 2019 at 8:4 Comment(6)
geom_text adds (20,20) for each row in mtcarsContravention
Yeah, I suspected this. But why does this happen when I specified only one value for x, y, and label? And how do I resolve this in the geom_label_repel case?Rodeo
You should pass different data for such annotation, for example: geom_text(aes(20, 20, label = "(20,20)"), data.frame()) or geom_label_repel(aes(20, 20, label = "(20,20)"), data.frame())Contravention
Holy s..., this works! And also for the case of ggplot(mtcars) + aes(x = mpg, y = qsec) + geom_line() + geom_label_repel(aes(x = 20, y = 20, label = "(20,20)"), data.frame())Rodeo
Thanks! If you want, write it up as an answer and I'll accept it. Still don't fully understand why data = NULL doesn't work.Rodeo
In documentation it says that data is "A data frame. If specified, overrides the default data frame defined at the top level of the plot". NULL doesn't override it.Contravention
C
4

geom_text or geom_label_repel adds one label per row. Therefore you can submit a separate dataset for annotation geom. For example:

library(ggplot2)
library(ggrepel)
ggplot(mtcars, aes(mpg, qsec)) +
    geom_line() +
    geom_label_repel(aes(20, 20, label = "(20,20)"), data.frame())

enter image description here

Contravention answered 27/2, 2019 at 8:12 Comment(0)
H
10

Add "check_overlap = TRUE" to geom_text to prevent overplotting.

library(ggplot2) 

ggplot(mtcars) +
        aes(x = mpg, y = qsec) +
        geom_line() +
        geom_text(x = 20, y = 20, label = "(20,20)", check_overlap = TRUE)

enter image description here

Hypogene answered 12/5, 2020 at 20:40 Comment(2)
Tjebo, it works, adding "check_overlap = TRUE" to geom_text, as shown above, prevents overplotting.Hypogene
My bad! I tested it yesterday using R online (me not being at home) and it somehow did not work. The downvote is not mine btw.Duress
C
4

geom_text or geom_label_repel adds one label per row. Therefore you can submit a separate dataset for annotation geom. For example:

library(ggplot2)
library(ggrepel)
ggplot(mtcars, aes(mpg, qsec)) +
    geom_line() +
    geom_label_repel(aes(20, 20, label = "(20,20)"), data.frame())

enter image description here

Contravention answered 27/2, 2019 at 8:12 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.