Adding text annotations in a data-independent manner in R

Viewed 124

I am trying to annotate many plots iteratively. I want an annotation to appear in the exact same place on all graphs, but they all have different y-axis scales. How do I annotate a graph without using the y-values? There must be a data-independent way, but I think I am missing a key piece of vocabulary so my searching has been fruitless.

Normally, I would add, e.g., annotate("text", x = 5, y = 10) to the ggplot object, but this doesn't work because the range of y varies widely between groups.

Bearing in mind there are around 30 plots to keep track of, here is a toy example using mtcars and ggpubr.

library(ggpubr)
ggboxplot(mtcars, x = "gear", y = "wt") +
  annotate("text", x = 2, y = 5, label = "I should be in the same place in both plots")
ggboxplot(mtcars, x = "gear", y = "disp") + 
  annotate("text", x = 2, y = 5, label = "I should be in the same place in both plots")

wt

disp

3 Answers

You could use inset_element from patchwork to overlay a plot consisting of just the label on top of each other plot.

library(ggpubr)
library(patchwork)

label <- ggplot() + 
  annotate("text", x = 2, y = 5, label = "I should be in the same place in both plots") +
  coord_cartesian(clip = "off") +   # allows text to overflow if needed
  theme_void()
ggboxplot(mtcars, x = "gear", y = "wt") +
  inset_element(label, left = 0.4, bottom = 0.7, right = 0.8, top = 0.8)
ggboxplot(mtcars, x = "gear", y = "disp") + 
  inset_element(label, left = 0.4, bottom = 0.7, right = 0.8, top = 0.8)

enter image description here

enter image description here

We could go one step further and define:

label_layer <- inset_element(label, left = 0.4, bottom = 0.7, 
                             right = 0.8, top = 0.8) 

Then each plot could be:

ggboxplot(mtcars, x = "gear", y = "wt") + label_layer

Devide the first y by 100:

library(ggpubr)
ggboxplot(mtcars, x = "gear", y = "wt") +
  annotate("text", x = 2, y = 5/100, label = "I should be in the same place in both plots")
ggboxplot(mtcars, x = "gear", y = "disp") + 
  annotate("text", x = 2, y = 5, label = "I should be in the same place in both plots")

enter image description here enter image description here

You can pass a percentage of the maximum value of the axis. It doesn't get them always in the same spot but it gets pretty close.

library(ggpubr)
ggboxplot(mtcars, x = "gear", y = "wt") +
  annotate("text", y = max(mtcars$wt)*.9, x = 2, label = "I should be in the same place in both plots")
ggboxplot(mtcars, x = "gear", y = "disp") + 
  annotate("text", y = max(mtcars$disp)*.9, x = 2, label = "I should be in the same place in both plots")

enter image description here

enter image description here

Related