Search code examples
rggplot2gganimate

Use gganimate to successively draw lines and then fade


I'm trying to work on an animation for an upcoming presentation but have hit a bit of a wall. What I'm trying to do is have gganimate draw lines for several species, one after the other, and once a line has finished being drawn have it either fade or change to gray so the new lines are more obvious. I've gotten the first part of that working fine (see example below) but can't seem to figure out a way to make the lines fade. I tried looking around but couldn't find any other solutions posted anywhere.

library(tidyverse)
library(gganimate)

# Create some data
year <- rep(c(1:10),2)
type <- c(rep(c("A"),10), rep(c("B"),10))
count <- floor(runif(20,1,15))

df <- data.frame(year, type, count)

# Creat index variable for animation
df$index <- 1:nrow(df)

ggplot(df, aes(x = as.factor(year), y = count, color = type)) +
  geom_line(aes(group = type),
            lwd = 1) +
  transition_reveal(index)

Solution

  • A bit clunky as transition_manual doesn't animate between different states, but this will give you the control to fade lines in their entirety after gradually revealing them:

    df %>%
      # make sure index follows appropriate order
      arrange(type, year) %>%
      mutate(index = seq.int(n())) %>% 
      
      # blow up dataset so that each frame captures all the data required in that frame
      uncount(n(), .id = "frame") %>%
      filter(index <= frame) %>%
      
      # manually add transparency condition to fade line after each type has been
      # fully shown (currently alpha set as 0.5; can change to other values if desired)
      mutate(group = as.integer(factor(type))) %>%
      group_by(frame) %>%
      mutate(current.group = max(group),
             alpha = ifelse(group == current.group, 1, 0.5)) %>%
      ungroup() %>%
      select(-c(current.group, group)) %>%
      
      # plot animate
      ggplot(aes(x = as.factor(year), y = count, color = type, alpha = alpha, group = type)) +
      geom_line(lwd = 1) +
      scale_alpha_identity() +
      transition_manual(frame)
    

    result plot

    Solution inspired by Jon Spring's answer here.

    Data used:

    set.seed(123)
    df <- data.frame(year = rep(c(1:10),2),
                     type = c(rep(c("A"),10), rep(c("B"),10)),
                     count = floor(runif(20,1,15)))