Search code examples
rggplot2colorslabelannotate

Annotate ggplot with multiple coloured text annotations the same as the legend / plot features


I'm trying to annotate a ggplot that shows multiple results of the same response on different days. When I plot the data, I set col = day in the aes command. How do I annotate the ggplot with mean values of the response on each day using the same colours that ggplot used to draw the plot and for the legend?

Here's a simple example

library(ggplot2)

# generate some dummy data - col_var in this example takes the place of day in the real example

data <- data.frame ( col_var = rep(c('A', 'B', 'C'), each = 10), x = rep(1:10, 3), y = rep(rnorm(10, 3, 1), each = 3))

# establish means for each response (y)

data_means <- data.frame ( col_var = unique(data$col_var), means = tapply(data$y,list(data$col_var),mean,na.rm=T))

# plot the data 

p <- ggplot(data, aes(x = x, y = y, col = col_var)) + 
  geom_line()+
  ylim(0, 10)

Here's where I get stuck. I would like to add the mean values, stacked one on top of each other in the same order as they appear in the legend from data_means to the plot and colour them the same as the geom_line for each col_var

p + geom_text(data_means, aes(label = means, col = col_var ), x = 2, y = 5)

p + annotate(data_means, aes(label = means, col = col_var ), x = 2, y = 5)

Solution

  • Update:

    libray(dplyr)
    library(ggplot2)
    
    data %>% 
      group_by(col_var) %>% 
      mutate(means = mean(y)) %>%
      ggplot(aes(x = x, y = y, group = means, color = col_var)) + 
      geom_line() +
      ylim(0,10)+
      scale_x_discrete(expand=c(0, 1)) +
      geom_text(data = data_means, aes(label = paste0("Mean ", col_var[1], " = ", round(means[1],2)), x = 4, y=8.5, color = factor(means)[1]))+
      geom_text(data = data_means, aes(label = paste0("Mean ", col_var[2], " = ", round(means[2],2)), x = 4, y=8, color = factor(means)[2]))+
      geom_text(data = data_means, aes(label = paste0("Mean ", col_var[3], " = ", round(means[3],2)), x = 4, y=7.5, color = factor(means)[3]))+
      scale_color_manual(values = c("red", "green", "blue", "red", "green", "blue"))+
      theme(legend.position = "none")
    

    enter image description here

    First answer:

    Annotating geom_line is not as trivial as one might think. This is discussed and handled very well here: Plot labels at ends of lines

    I think in your case directlabels package is appropriate: We first add a column with the means to the data.

    library(ggplot2)
    #install.packages("directlabels")
    library(directlabels)
    library(dplyr)
    
    
    data %>% 
      group_by(col_var) %>% 
      mutate(means = mean(y)) %>%
      ggplot(aes(x = x, y = y, group = means , colour = col_var)) + 
      geom_line() +
      ylim(0,10)+
      scale_x_discrete(expand=c(0, 1)) +
      geom_dl(aes(label = round(means, 3)), method = list(dl.combine("last.points")), 
              position = position_nudge(y = c(0.2, 0, 0))) 
    

    enter image description here