Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way to pause at specific frames/time points with transition_reveal in gganimate?

Tags:

r

gganimate

Utilising this example from the package's wiki on Github:

airq <- airquality
airq$Month <- format(ISOdate(2004,1:12,1),"%B")[airq$Month]

ggplot(airq, aes(Day, Temp, group = Month)) + 
  geom_line() + 
  geom_segment(aes(xend = 31, yend = Temp), linetype = 2, colour = 'grey') + 
  geom_point(size = 2) + 
  geom_text(aes(x = 31.1, label = Month), hjust = 0) + 
  transition_reveal(Month, Day) + 
  coord_cartesian(clip = 'off') + 
  labs(title = 'Temperature in New York', y = 'Temperature (°F)') + 
  theme_minimal() + 
  theme(plot.margin = margin(5.5, 40, 5.5, 5.5))

Produces something like:

enter image description here

I wanted to know if there is any way to define pausing in the animation at specific points. For e.g. at Day 10, then 20, then when the animation is finished, before looping again. geom_reveal has no state_length or transition_length arguments available so I'm not sure if this is possible.

Edit: the package author mentions it's possible on twitter but I don't know what 'reveal timing' argument he is referring to.

like image 717
Nautica Avatar asked Oct 31 '18 21:10

Nautica


1 Answers

From OP:

Edit: the package author mentions it's possible [to do this] but I don't know what 'reveal timing' argument he is referring to.

On Twitter, Thomas Lin Pedersen was referring to how the transition_reveal line is driving the frames of the animation. So we can feed it one variable to be the "heartbeat" of the animation, while leaving the original variables for the plots.

My first approach was to make a new variable, reveal_time, which would be the heartbeat. I would increment it more at pause points, so that the animation would spend more time on those data points. Here I did that by adding 10 at the pause point days, and only 1 on other days.

library(dplyr)
airq_slowdown <- airq %>%
  group_by(Month) %>%
  mutate(show_time = case_when(Day %in% c(10,20,31) ~ 10,
                                     TRUE           ~ 1),
         reveal_time = cumsum(show_time)) %>%
  ungroup()

Then I fed that into the animation, changing the source data frame and the transition_reveal line.

library(gganimate)
a <- ggplot(airq_slowdown, aes(Day, Temp, group = Month)) + 
  geom_line() + 
  geom_segment(aes(xend = 31, yend = Temp), linetype = 2, colour = 'grey') + 
  geom_point(size = 2) + 
  geom_text(aes(x = 31.1, label = Month), hjust = 0) + 
  transition_reveal(reveal_time) +  # Edit, previously had (Month, reveal_time)
  coord_cartesian(clip = 'off') + 
  labs(title = 'Temperature in New York', y = 'Temperature (°F)') + 
  theme_minimal() + 
  theme(plot.margin = margin(5.5, 40, 5.5, 5.5))    
animate(a, nframe = 50)

enter image description here

But when I did that, I realized that it wasn't pausing -- it was just slowing down the tweening. Sort of a "bullet time" effect -- cool but not quite what I was looking for.

So my second approach was to actually copy the paused lines of the animation. By doing so, there would be no tweening and there would be real pauses:

airq_pause <- airq %>%
  mutate(show_time = case_when(Day %in% c(10,20,31) ~ 10,
                               TRUE           ~ 1)) %>%
  # uncount is a tidyr function which copies each line 'n' times
  uncount(show_time) %>%
  group_by(Month) %>%
  mutate(reveal_time = row_number()) %>%
  ungroup()

enter image description here

like image 151
Jon Spring Avatar answered Oct 20 '22 05:10

Jon Spring