gganimate extends the grammar of graphics as implemented by ggplot2 to include the description of animation. It does this by providing a range of new grammar classes that can be added to the plot object in order to customise how it should change with time.

library(ggplot2)
library(gganimate)

Animate a qualitative variable

Here we take a simple boxplot of fuel consumption as a function of cylinders and lets it transition between the number of gears available in the cars. As this is a discrete split (gear being best described as a qualitative variable) we use transition_states and provides a relative length to use for transition and state (pause) view. As not all combinations of data is present there are states missing a box. We define that when a box appears it should fade into view, whereas it should shrink away when it disappears. Lastly we decide to use a sinusoidal easing for all our aesthetics (here, only y is changing). We also see the use of string literal interpolation in titles.

levels(factor(mtcars$cyl))
levels(factor(mtcars$gear))

ggplot(mtcars, aes(factor(cyl), mpg)) + 
  geom_boxplot() + 
  # Here comes the gganimate code
  transition_states(
    gear,
    transition_length = 2,
    state_length = 1
  ) +
  enter_fade() + 
  exit_shrink() +
  ease_aes('sine-in-out') + 
  labs(title = 'Fuel consumption for {closest_state} gears', x = 'cyl')


anim_save("mtcars.gif")

Animate a quantitative variable

In this example we see the use of transition_time() which can be used with quantitative variables such as year. With this transition it is not necessary to provide transition and state length as the “transition variable” provides this directly. We also depict a wake for the points using shadow_wake() function.

library(gapminder)

ggplot(gapminder, aes(gdpPercap, lifeExp, size = pop, colour = country)) +
  geom_point(alpha = 0.7, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 12)) +
  scale_x_log10() +
  facet_wrap(~continent) +
  # Here comes the gganimate specific bits
  labs(title = 'Year: {frame_time}', x = 'GDP per capita', y = 'life expectancy') +
  transition_time(year) +
  ease_aes('linear') +
  shadow_wake(0.25, wrap = FALSE)

anim_save("gapminder.gif")

Let’s make a focus on the African continent:

library(dplyr)

gapminder %>% 
  filter(continent == "Africa") %>%
  ggplot(aes(gdpPercap, lifeExp, size = pop, colour = country)) +
  geom_point(alpha = 0.5, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 20)) +
  scale_x_log10() +
  theme_minimal() +
  # Here comes the gganimate specific bits
  labs(title = 'Year: {frame_time}', x = 'GDP per capita (log)', y = 'life expectancy') +
  transition_time(year) +
  ease_aes('linear') +
  shadow_wake(0.20, wrap = FALSE)

anim_save("gapminderAfrica.gif")

Let’s compare with Europe:

gapminder %>% 
  filter(continent == "Europe") %>%
  ggplot(aes(gdpPercap, lifeExp, size = pop, colour = country)) +
  geom_point(alpha = 0.5, show.legend = FALSE) +
  scale_colour_manual(values = country_colors) +
  scale_size(range = c(2, 20)) +
  scale_x_log10() +
  theme_minimal() +
  # Here comes the gganimate specific bits
  labs(title = 'Year: {frame_time}', x = 'GDP per capita (log)', y = 'life expectancy') +
  transition_time(year) +
  ease_aes('linear') +
  shadow_wake(0.20, wrap = FALSE)

anim_save("gapminderEurope.gif")