Search code examples
rggplot2tidyversegeom-text

Annotate a geom_smooth line in ggplot


Given the following dummy dataset

df = structure(list(date = structure(c(19128, 19129, 19130, 19131, 
                                   19132, 19133, 19134, 19135, 19136, 19137, 19138, 19139, 19140, 
                                   19141, 19142, 19143, 19144), class = "Date"), av7 = c(108.55, 
                                                                                         108.875, 108.916666666667, 108.725, 108.92, 108.877777777778, 
                                                                                         108.841666666667, 108.70119047619, 108.525, 108.329761904762, 
                                                                                         108.115476190476, 107.94880952381, 107.877380952381, 107.652380952381, 
                                                                                         107.609523809524, 107.495238095238, 107.390476190476), ch7 = c(-0.15, 
                                                                                                                                                        -0.35, -0.59, -0.61, -0.97, -1, 0, 0.15, -0.35, -0.59, -0.61, -0.97, -1, 
                                                                                                                                                        -1.19, -1.09, -1.03, -0.94)), row.names = c(NA, -17L), class = c("tbl_df", 
                                                                                                                                                                                                                         "tbl", "data.frame"))

I would like to make a smooth line for the av7 variable and annotate that line with values from the ch7 variable. I tried this code:

ggplot(df, aes(x = date, y=av7, label = ch7))+
  geom_smooth(se=F)+
  geom_text(nudge_y = 0.2)

However, As you can see below, the position of the label does not align with the of the smoothed line as it follows the position of the original points:

enter image description here

I also tried to use stat = "smooth" witin geom_text as follows:

ggplot(df, aes(x = date, y=av7, label = ch7))+
  geom_smooth(se=F)+
  geom_text(nudge_y = 0.2,
            stat = "smooth")

But I got the following error:

Error: geom_text requires the following missing aesthetics: label

Any help would be much appreciated.


Solution

  • One approach is to assign the values of the loess smooth to the original data frame, and then plot the line and the points separately:

    df <- df %>% mutate(sm = predict(loess(av7~as.numeric(date), data=df)))
    
    ggplot(df, aes(x = date, y=sm, label = ch7))+
      geom_line(color="blue") + geom_text(nudge_y=0.2)
    

    enter image description here