6

I am starting to get familiar with gganimate, but I want to extend my gifs further.

For instance, I can throw a frame on one variable in gganimate but what if I want to animate the process of adding entirely new layers/geoms/variables?

Here's a standard gganimate example:

library(tidyverse)
library(gganimate)

p <- ggplot(mtcars, aes(x = hp, y = mpg, frame = cyl)) +
    geom_point()

gg_animate(p)

But what if I want the gif to animate:

# frame 1
ggplot(mtcars, aes(x = hp, y = mpg)) +
    geom_point()

# frame 2
ggplot(mtcars, aes(x = hp, y = mpg)) +
    geom_point(aes(color = factor(cyl)))

# frame 3
ggplot(mtcars, aes(x = hp, y = mpg)) +
    geom_point(aes(color = factor(cyl), size = wt))

# frame 4
ggplot(mtcars, aes(x = hp, y = mpg)) +
    geom_point(aes(color = factor(cyl), size = wt)) +
    labs(title = "MTCARS")

How might this be accomplished?

emehex
  • 9,874
  • 10
  • 54
  • 100

3 Answers3

8

You can manually add a frame aesthetic to each layer, though it will include the legends for all of the frames immediately (Intentionally, I believe, to keep ratios/margins, etc. correct:

saveAnimate <-
  ggplot(mtcars, aes(x = hp, y = mpg)) +
  # frame 1
  geom_point(aes(frame = 1)) +
  # frame 2
  geom_point(aes(color = factor(cyl)
                 , frame = 2)
             ) +
  # frame 3
  geom_point(aes(color = factor(cyl), size = wt
                 , frame = 3)) +
  # frame 4
  geom_point(aes(color = factor(cyl), size = wt
                 , frame = 4)) +
  # I don't think I can add this one
  labs(title = "MTCARS")

gg_animate(saveAnimate)

enter image description here

If you want to be able to add things yourself, and even see how legends, titles, etc. move things around, you may need to step back to a lower-level package, and construct the images yourself. Here, I am using the animation package which allows you to loop through a series of plots, with no limitations (they need not be related at all, so can certainly show things moving the plot area around. Note that I believe this requires ImageMagick to be installed on your computer.

p <- ggplot(mtcars, aes(x = hp, y = mpg))

toSave <- list(
  p + geom_point()
  , p + geom_point(aes(color = factor(cyl)))
  , p + geom_point(aes(color = factor(cyl), size = wt))
  , p + geom_point(aes(color = factor(cyl), size = wt)) +
    labs(title = "MTCARS")
)

library(animation)

saveGIF(
  {lapply(toSave, print)}
  , "animationTest.gif"
 )

enter image description here

Mark Peterson
  • 9,370
  • 2
  • 25
  • 48
  • Pretty slick. I don't think I've ever seen an animated display on SO before. I thought SO only displayed png files. Now we just need to slow it down a littel bit, but that would perhaps be another question. – IRTFM Oct 06 '16 at 20:12
  • The help for `saveGIF` points to `ani.options` which includes `interval` which sets the time each frame stays (in seconds). So, just adding `interval = 3` would get you 3 seconds per frame – Mark Peterson Oct 06 '16 at 20:25
  • Fo a moment it appeared you must have added code to hold the legends in a fixed format, but that impression went away as the page refreshed. Oh, never, mind... the upper one has that feature and the lower one does not. – IRTFM Oct 06 '16 at 20:27
2

The gganimate commands in the earlier answers are deprecated as of 2021 and won't accomplish OP's task.

Building on Mark's code, you can now simply create a static ggplot object with multiple layered geoms and then add the gganimate::transition_layers function to create an animation that transitions from layer to layer within the static plot. Tweening functions like enter_fade() and enter_grow() control how elements change into and out of frames.

library(tidyverse)
library(gganimate)

anim <- ggplot(mtcars, aes(x = hp, y = mpg)) +
  # Title
  labs(title = "MTCARS") +
  # Frame 1
  geom_point() +
  # Frame 2  
  geom_point(aes(color = factor(cyl))) +
  # Frame 3
  geom_point(aes(color = factor(cyl), size = wt)) +
  # gganimate functions
  transition_layers() + enter_fade() + enter_grow()

# Render animation
animate(anim)

martinlu
  • 41
  • 4
  • welcome to SO. Great contribution. +1. The last frame is pointless. (although there are plenty of points drawn). The OP had intended to add a title here. Tried it - may be not that straight forward. – tjebo Jan 26 '21 at 21:26
  • Thanks for pointing out the accidental repeated `geom_point()`. Edited post to remove it and add a title, as OP specified. Adding a `labs(title = "")` call anywhere between the `ggplot()` call and `gganimate` functions seems to do it. – martinlu Jan 28 '21 at 04:47
0

the animation package doesn't force you to specify frames in the data. See the example at the bottom of this page here, where an animation is wrapped in a big saveGIF() function. You can specify the duration of individual frames and everything.

The drawback to this is that, unlike the nice gganimate functions, the basic frame-by-frame animation wont hold the plot dimensions/legend constant. But if you can hack your way into displaying exactly what you want for each frame, the basic animation package will serve you well.

Matt74
  • 729
  • 4
  • 8