1

I have the following dataframe in R

data <- structure(list(Date = structure(c(19541, 19542, 19543, 19544, 
19545, 19548, 19549, 19550, 19551, 19552, 19555, 19556, 19557, 
19558, 19559, 19562), class = "Date"), Value = c(18.7414, 18.6471, 
18.7749, 19.1089, 18.867, 18.7948, 18.4902, 18.135, 17.9282, 
18.1077, 18.0356, 17.8571, 17.8682, 17.9244, 17.96, 17.9832)), row.names = c(NA, 
-16L), class = c("tbl_df", "tbl", "data.frame"))

I've created an animated chart using my data and gganimate and I'm close to my desirable result. The only issue that I need advice with is on how to animate the geom_text and annotate that is in my chart as well, so that they only appear once my animated geom_line reaches the date in my chart that coincides with where my geom_text and annotate are. Is there a way to achieve this?

library(tidyverse)
library(lubridate)
library(gganimate)
library(cowplot)
library(magick)

p <- data %>% {
  ggplot(., aes(x = Date, y = Value)) +
    annotate("rect",  xmin = tail(.$Date, 1) - days(3), xmax = tail(.$Date, 1), 
             ymin = -Inf,  ymax = Inf, fill = "red", alpha= 0.3) +
    geom_line(linewidth = 1) +
    geom_text(aes(x = Date, label = sprintf("%.2f", Value)), hjust = 0,show.legend = F,fontface='bold',color='#16161E') +
    geom_text(aes(x = as.Date('2023-07-10'), y = 19, label = 'I want these words to be animated'), hjust = 0,show.legend = F,fontface='bold',color='#16161E') +
    theme_light() +
    coord_cartesian(clip = "off") +
    theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
          plot.margin = unit(c(1, 1, width, 1), "lines"), plot.title = element_text(colour = '#16161E'),
          legend.title = element_blank(), legend.position = 'bottom',
          plot.caption = element_text(hjust = 0)
    ) 
  } 


# Animate

p <- p + 
  transition_reveal(Date)


animate(p, height = 7, 
        width = 15, units = "in", res = 150, renderer = gifski_renderer(loop = FALSE))

anim_save("templatechart.gif")


enter image description here

Tanga94
  • 695
  • 6
  • 27

1 Answers1

1

For the text, just ifelse your text's label according to whether or not the plotted row exceeds the threshold Date. For the rectangle, switch to a geom_rect and use ifelse to fill:

p <- ggplot(mutate(data, reveal_col = row_number()),
            aes(x = Date, y = Value)) +
  geom_rect(aes(xmin = max(Date) - days(3), xmax = max(Date),
                ymin = -Inf, ymax = Inf, 
                fill = ifelse(reveal_col > nrow(data) - 1, NA, "#FF000060")),
            na.rm = TRUE) +
  geom_line(linewidth = 1) +
  geom_text(aes(x = Date, label = sprintf("%.2f", Value)),
            hjust = 0,show.legend = F,
            fontface='bold',color='#16161E') +
  geom_text(aes(x = as.Date('2023-07-10'), y = 19, 
                label = ifelse(reveal_col > match(as.Date("2023-07-10"), Date),
                               'I want these words to be animated', "")), 
            hjust = 0, fontface = 'bold', color = '#16161E') +
geom_segment(aes(x = as.Date('2023-07-10'), y = 18.8, xend = as.Date('2023-07-10'), yend = 19.0), linetype = ifelse(reveal_col > match(as.Date('2023-07-10'), Date), 'dashed')) +
  theme_light() +
  scale_fill_identity() +
  coord_cartesian(clip = "off") +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        plot.margin = unit(c(1, 1, 1, 1), "lines"), 
        plot.title = element_text(colour = '#16161E'),
        legend.title = element_blank(), legend.position = 'bottom',
        plot.caption = element_text(hjust = 0)) +
  transition_reveal(reveal_col)

animate(p, height = 4, width = 7, units = "in", res = 150)

enter image description here

Tanga94
  • 695
  • 6
  • 27
Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Thanks Allan! This is perfect. Is there a way to also animate the pink annotated shaded area so that also only appears when my geom_line reaches that date? – Tanga94 Aug 19 '23 at 13:14
  • @Tanga94 yes, it's a similar technique. See my update. – Allan Cameron Aug 19 '23 at 14:38
  • Thanks so much for the help Allan! This is exactly the solution I needed – Tanga94 Aug 20 '23 at 18:59
  • Sorry Allan I have one more question. I've added a ```geom_segment``` to your solution that I'm also trying to animate in the same way but I'm not able to get it to work. Should I add the ```ifelse``` & ```reveal_col``` argument to the ```linetype``` argument in ```geom_segment``` or is it supposed to go elsewhere in order to animate it? – Tanga94 Aug 20 '23 at 19:57