Search code examples
rggplot2gganimate

How to animate the axis label using `gganimate`?


I am actually very amazed to see I cannot quickly find a guide to how to do this. Here is an example:

library(ggplot2)
library(gganimate)
library(data.table)
library(magrittr)

dt <- lapply(seq(10), function(i){
    mean = i
    label = paste0("T = ", i)
    dt = data.table(x = seq(0, 50, length.out = 100))
    set(dt, j = "y", value = dt[, dlnorm(x, meanlog = log(mean), sdlog = 0.2)])
    set(dt, j = "frameN", value = i)
    return(dt)
}) %>% rbindlist

print(dt)

p <- ggplot(dt, aes(x = x, y = y)) +
  geom_line() +
  scale_x_continuous(name = "x", breaks = c(0, 1)) +
  transition_manual(frameN)

animate(p)

I want the breaks and labels of scale_x_continuous to follow my own definitions:

arr_breaks <- c(1, 3, 2, 4, 3, 5, 4, 6, 5, 7)
arr_labels <- paste0(seq(10, 100, 10), " kg")

And then

  • breaks = arr_breaks[1], labels = arr_labels[1] for frame 1
  • breaks = arr_breaks[2], labels = arr_labels[2] for frame 2

...

  • breaks = arr_breaks[10], labels = arr_labels[10] for frame 10

No matter how I do it I got errors. Any idea?


Solution

  • As @z-lin noted, gganimate is not currently set up (to my knowledge) to animate scales with different breaks. The effect could be closely approximated using geoms, and with some more work you could probably make an exact visual match to a changing scale.

    breaks_df <- data.frame(
    
    frameN = c(1:10),
      arr_breaks = c(1, 3, 2, 4, 3, 5, 4, 6, 5, 7),
      arr_labels = paste0(seq(10, 100, 10), " kg")
    )
    
    p <- ggplot(dt, aes(x = x, y = y)) +
      geom_segment(data = breaks_df, color = "white",
                   aes(x = arr_breaks, xend = arr_breaks,
                       y = -Inf, yend = Inf)) +
      geom_text(data = breaks_df, vjust = 3, size = 3.5, color = "gray30",
                aes(x = arr_breaks, y = 0, label = arr_labels)) +
      geom_line() +
      scale_x_continuous(name = "x", breaks = c(0)) +
      coord_cartesian(clip = "off") +
      transition_manual(frameN)
    animate(p, width = 600, height = 250)
    

    enter image description here