monkeytennis
monkeytennis

Reputation: 908

How to add single annotation to overall ggplot plot and not to each facet

I have a ggplot with two facets, each containing the same custom added reference line. I want to add a single annotation label for each line, and to specify the location for each label in terms of the position on the overall plot.

I have tried adding the labels using annotate but this adds a label to each individual facet.

How do I specify the location for a single label on the 'global', overall plotting area (analagous to how x and y behave for legend.position in the example below) when facets are involved?

library(ggplot2)

p <- mtcars %>% 
  ggplot(aes(x = mpg, y = disp, colour = am)) + 
  geom_point() + 
  geom_vline(aes(xintercept = 15), 
             linetype = "dotted",
             colour = "grey20") + 
  geom_vline(aes(xintercept = 25), 
             linetype = "dotted",
             colour = "grey20") + 
  facet_wrap(~vs, nrow = 2)

# desired behaviour is to position labels using x and y of overall plot area, as per positioning of legend 
p <- p + 
  # x and y refer to positions on overall plot here, not to values of variables within individual facets
  theme(legend.position = c(x = 0.9, y = 0.5))

# failed attempt adds labels to each facet
p <- p + 
  # x and y refer to individual facets/values of x and y variables here
  annotate("text", x = 15 , y = 0.5,
           label = "This label\nshould be on midpoint of y", 
           colour = "grey50") +
  annotate("text", x = 25 , y = 0.75,
           label = "This label\nshould be 3/4 up plot", 
           colour = "grey50")
 
# show plot
p

example_ggplot_output

Thanks!

Upvotes: 1

Views: 1831

Answers (2)

tjebo
tjebo

Reputation: 23737

Note, any annotation of that sort will be somewhat hacky and will require careful adjustment of the position of your labels. I think most convenient should be using either patchwork or cowplot for custom annotation. Cowplot offers specific functionality for plot labelling.

library(tidyverse)
library(cowplot)

p <- mtcars %>% 
  ggplot(aes(x = mpg, y = disp, colour = am)) + 
  geom_point() + 
  geom_vline(aes(xintercept = 15), 
             linetype = "dotted",
             colour = "grey20") + 
  geom_vline(aes(xintercept = 25), 
             linetype = "dotted",
             colour = "grey20") + 
  facet_wrap(~vs, nrow = 2) +
  theme(legend.position = c(x = 0.9, y = 0.5))

# desired behaviour is to position labels using x and y of overall plot area, as per positioning of legend 
ggdraw(p) + draw_plot_label(x = c(.2,.6), y = c(.6,.6), 
                       label =  c("This label\nshould be on midpoint of y",  "This label\nshould be 3/4 up plot"),
                       hjust = 0, size = 9)

Created on 2021-03-03 by the reprex package (v1.0.0)

Upvotes: 1

Francesco Grossetti
Francesco Grossetti

Reputation: 1595

You can use grid::grid.text() to position a specific label in your canvas. Use it multiple times to achieve what you want. Of course, also adjust the position of the label.

Please, have a look at the code below.

library(ggplot2)
library(magrittr)
library(grid)

p <- mtcars %>% 
  ggplot(aes(x = mpg, y = disp, colour = am)) + 
  geom_point() + 
  geom_vline(aes(xintercept = 15), 
             linetype = "dotted",
             colour = "grey20") + 
  geom_vline(aes(xintercept = 25), 
             linetype = "dotted",
             colour = "grey20") + 
  facet_wrap(~vs, nrow = 2)

p
grid.text("text1", x = 0.5, y = 0.5)
grid.text("text2", x = 0.5, y = 0.75)

Is this what you would like to have?

Created on 2021-03-03 by the reprex package (v1.0.0)

Upvotes: 2

Related Questions