Search code examples
rggplot2texttextboxlabel

ggplot2: proper way to add a text box label to a scatter plot


I have the following MWE with iris data, I just want to make a scatter plot with a text box label on top of the plot area.

This is my input data:

data(iris)
set.seed(123)
iris$Group <- sample(LETTERS[1:2], nrow(iris), replace = T)
iris$Highlight <- FALSE
iris$Highlight[iris$Species=="setosa"] <- TRUE
iris$Highlight <- factor(iris$Highlight, levels=c(TRUE, FALSE))
iris$Group[iris$Highlight==FALSE] <- NA
iris$Group <- factor(iris$Group, levels=LETTERS[1:2])
plot_palette <- c("#E41A1C","#377EB8")

I first try to make the plot I want, without any text box label:

P <- ggplot2::ggplot(iris, ggplot2::aes(x=Sepal.Length, y=Sepal.Width, color=Group)) +
  ggplot2::geom_point(size=5, alpha=0.5, shape=16) +
  ggplot2::scale_color_manual(values=plot_palette, drop=FALSE,
                              guide=ggplot2::guide_legend(ncol=2, override.aes=list(shape=19, size=8)),
                              na.value="grey75", breaks=LETTERS[1:2]) +
  ggplot2::theme_light() +
  ggplot2::theme(axis.text=ggplot2::element_text(size=15),
                 axis.title=ggplot2::element_text(size=15,face="bold"),
                 legend.text=ggplot2::element_text(size=18),
                 legend.title=ggplot2::element_text(size=15,face="bold"),
                 legend.position="bottom",
                 legend.key.size=grid::unit(0.5,"inch"),
                 plot.margin = grid::unit(c(2,2,0,2), "lines"))
grDevices::png(filename="test1.png", height=600, width=600)
print(P)
grDevices::dev.off()

This produces the plot exactly the way I want:

test1

However, now I just want to add a text box to the plot area, and it's when things get messy. I tried geom_text and geom_label as specified in multiple places:

P <- P + ggplot2::geom_label(x=4.5, y=4, label="this is\nmy label")

...and still this is the best I get:

test2

Why does the label show in the legend? What am I doing wrong here?

If you can include in the answer how to modify the text (color, size, make it justified), and the box (background color, line thickness...), and most importantly, the box anchor point, that would be awesome.

PS: It doesn't actually have to be a box, just text would do... solutions with both geom_label and geom_text would be appreciated.

Thanks!


Solution

  • Try ggplot2::annotate("label",x=4.5, y=4, label="this is\nmy label")

    geom_label, like most geom_* functions (but not, for example, geom_vline), makes a layer reflecting each observation in the data. i.e. the label will be created 150 times, once for each observation, and respecting the global aesthetic mapping of group to color. The label here is added to the legend, another unwanted side effect.

    annotate("label", ....) makes a layer apart from the data and any global aesthetics. See https://ggplot2.tidyverse.org/reference/annotate.html

    enter image description here