Search code examples
rggplot2ggrepel

ggplot add annotation box, arrow with dynamic value in it


I am trying to add an annotation box in plot (using ggplot). I have added the text using text geom in annotate. The logic should be - every time when we generate the plot, it should have the text box with latest month and value in it. And the text box should point the corresponding value in the plot using an arrow or line. Here is what I tried so far,

 myplot <-  ggplot(sa_dat1,  aes(x = variable,  y = value )) + 
        theme_minimal() +
        geom_line(linetype = "solid", color = "#0072CE",size=1) +
        geom_smooth(method="loess", se=FALSE , linetype = "dashed", color="black", size = 0.5) + 
        scale_x_date(labels = date_format("%b-%Y"), date_breaks  ="2 month",expand = c(0.005,0)) +
        theme(axis.text.x = element_text(angle = 90, hjust = 1,vjust=0.5)) +
        scale_y_continuous(limits=c(ylimitmin5,ylimitmax5), labels=dollar_format(prefix="$"),
                 breaks  = seq(ylimitmin5, ylimitmax5, by = 10000),
                 expand = c(0,0)) +
        annotate("text", x=floor_date(max(sa_dat1$variable), "month") - months(12), 
           y= max(sa_dat1$value) - 20000, label = paste0("April 2017\n",
paste("$",round(max(sa_dat1$value)))))

And here is what I have got, enter image description here

What I am aiming for is this, I don't know how to add the arrow and text box around my text.

enter image description here


Solution

  • From comments above:

    annotate(geom = "label", ...) instead of "text" gets you a box around the text that you can modify with fill, border, etc.

    Just a shot in the dark, not tested: +annotate("segment", x=floor_date(max(sa_dat1$variable), "month") - months(12), xend = floor_date(max(sa_dat1$variable), "month"), y= max(sa_dat1$value) - 20000, yend= max(sa_dat1$value), arrow = arrow())

    Finally, you can adjust the start and end of the arrow using the values of the x and y aesthetics, just like you already adjusted them for the label. Maybe try -months(8) and -10000.


    Edited to add:

    • Call library(lubridate) to use months() and floor_date()