
Thomas Lin Pedersen | gganimate live cookbook | RStudio (2019)
Animation of data visualisation is becoming increasingly popular both as an attention grabber on social media and as a way to tell small data stories. gganimate is a package that extends ggplot2 for making animations and provides a grammar of animation on top of the grammar of graphics. This talk will quickly introduce gganimate, and then dive into a series of different animation and show how they were made and how they could be changed or expanded. Slides: https://data-imaginist.com/slides/rstudioconf2019 4 Resources: https://resources.rstudio.com/rstudio-conf-2019/gganimate-live-cookbook 4 Discussion https://community.rstudio.com/t/gganimate-live-cookbook-thomas-lin-pedersen-rstudio-conf-2019l-video/24852
image: thumbnail.jpg
Transcript#
This transcript was generated automatically and may contain errors.
Welcome to my talk. Thank you for joining me. I'm going to talk a bit about what I have been doing in mostly last year. First of all, I started at RStudio a couple of months ago, so that's pretty great. I am working on improving a lot of stuff with relation to this, but this is kind of my last year project. It will probably get some more support on, but right now it's done kind of stuff.
What is gganimate?
What is gganimate? gganimate is a package I have wrote. It's kind of a two-fold thing. It's both a grammar of graphics, like a theoretical backbone of how to describe animation, and it's also an implementation of said theoretical backbone. In the same sense that there exists a grammar of graphics theory, and ggplot2 is just one of many different implementations of this theory, what I wanted to do with gganimate was also to kind of build a theoretical backbone for how to address animation and data visualization. It's two-fold, and on top of that, it's an extension to ggplot2, so it's not something that exists on its own. It is something that you can apply to any of your normal ggplot2 plots and make them move magically.
Lastly, gganimate is not what it was a year ago. gganimate actually has a long storied history, starting with years ago, David Robinson, who sits down there, wrote gganimate, and he had some other thoughts than me about how it should look, and he made it, and it was fantastic, and it got pretty popular, and at some point he made the big mistake of asking me to take it over, and I had some other thoughts. So I rewrote it completely, which also means that if you have code from a year ago, I can assure you that it won't run. So I have broken a lot of stuff, but I think I've done it for good reasons. Furthermore, David never made it to CRAN with his package. I did, so it is now on CRAN, and you can grab it from there.
The grammar of animation
So how do I use gganimate? I'm not going to go too deep into the theoretical underpinnings of gganimate in this talk. This is more of how to get you started doing your first animations, but just to give you a bit of context, there are at least three quite important parts of the grammar of animations. Probably the most important part is what's called transitions, or what I've called transitions, which is you have some data you wanted to change over the course of the animations, then you need a transition. There's also something called views, which is you want your view, which is the Y and X scale, to change during the animation. How do you specify that? And then there's something called shadows, which is completely different, which is you want the animation to have some sort of memory.
You might be like, what? Which is fair enough. This is a one-slide overview of the grammar, so if you want to understand a bit more about the concepts of these, there is a web page, gganimate.com, and there's a getting started guide, which kind of holds your hand through your first different types of animations and talks a bit about that. Further, I had a presentation at Yusr last year, which went into much more detail about my reasons for doing these kind of things. So do check them out if you want to understand a bit more about what I'm talking about right now.
First example: Gapminder data
So diving headlong into the first example, this is a data set that a lot of people are familiar with, and in the context of animation, it's also quite important, because Hans Rosling became quite famous with presenting exactly this data set. This is an overview of how different countries have evolved in terms of population, in terms of life expectancies, in terms of GDP per capita, and Hans Rosling really showed how animation can be used as great, great storytelling devices in terms of communicating this data set. So let's play with it a bit.
This is a static version. Of course, if I wanted to make a static plot, this is probably not how I wanted to do it, but this is kind of our starting point for our animation. We make it as we would with a ggplot. There's a lot of code up there, but it shouldn't be that problematic. It's standard ggplot code. And we wind up with this horribly over-plotted scatterplot. So how do we make this move? Well, it's actually quite simple. Here we want to animate it over year, and year is a continuous variable, so we use the transition time function, and we give it year and say, well, do something with this. And what we get is, wait, it's moving.
There's actually a lot of stuff that happens behind the scene here, because what you're seeing is not only the underlying data, but as you can see, it's moving quite smoothly, even though the data doesn't support it. gganimate will interpolate your data to ensure that your animation is smooth, and it will do it in such a way that if I asked for like 10,000 frames for a four-minute animation of this, it will create enough frames to make it smooth. So it's not something that you do up front. You don't have to worry about the length of your animation when you're coding it. It's something that's done when it's rendered. So the specification of the animation is kind of unitless in that sense. So that's it. That's how you use gganimate. Any questions?
gganimate will interpolate your data to ensure that your animation is smooth, and it will do it in such a way that if I asked for like 10,000 frames for a four-minute animation of this, it will create enough frames to make it smooth.
There's, of course, a lot more to it. For instance, if you want this kind of animation, you don't really have a scale in the same way that you have a scale for your x-axis. A progress bar would be some sort of scale that allowed you to see where you were in your animation. I don't have that yet. I'm looking into it. But one thing you can do is that you can change your titles or your labels on your plot. And one way you can do this is that I've added support for the glue package, which allows you to insert different variables into your different titles and labels on your plot. And the different transitions gives you different variables that you can input, depending on which kind of transitions you have. So here we have the frame time. So each frame will actually expose the time that this frame is meant to be. And we can see that it updates nicely. And this actually allows for quite a powerful way of changing your labels during plotting.
Views and shadows
I would say that that's the end of this animation. But let's try to play a little bit with it. The following animations probably won't be better, but they will be different. We can add a view to it. Like we talked about, we can use a view to update the extent of the animation. Here we say we'll use view follow. View follow will simply look at the data that is in each frame and just kind of enclose that. And I'm setting fixed y to say, well, don't mess with the y-axis. Just update the x-axis to fit the data in. And we can see that, well, it does that. I would say that these kind of changing scales are used with care. They should be used with care. They can be quite disorienting. I don't think that it adds anything positive to this plot, but just to kind of show off the views.
We can also do other stuff, like the shadows. Shadows were probably the most part of that slide that you saw, something with memory and all that. It's kind of a weird concept, but when you see the result, it kind of makes sense. So here we add something called a shadow wake, which is something that allows you to trail the old frames in the current frame. So what you see here is that we add kind of a trail behind the points. And this is what I mean with memory. So what you're seeing is the old data from the previous frames actually being shown in the current frame. Now, this looks super cutie and not necessarily super important. There is actually use for such a thing as this. I wouldn't say that it's useful for this. It just adds over-plotting. But what these kind of trails can show you is both it can show you some kind of momentum, how fast are things moving, in which direction are they moving. So they can actually allow you to better position yourself during the animation.
Just to show, beat the dead horse, there's other types of shadows. Here's something called shadow mark, which allows you to keep raw data points in your animation as the animation progresses. And you can change the aesthetics of that data point. So as you can potentially see, you can see that a lot of points are being left behind as this animation evolves. Again, this is probably not the best use case for it. But if you have fewer data points, it can actually allow you to remember where the different raw data actually was during the animation.
Temperature data and transition reveal
OK, new example. This is some temperature data that I fetched in. Don't look too much at that code. It's just for reproducibility. This is just grabbing a lot of temperature measurements in Copenhagen and Austin to kind of justify why I went here for January. And the static version is just quite a similar line graph. And as you can see, it should at least be quite a bit warmer here. So I made the right choice.
So how would I want to animate that? Well, if I wanted to appear for one day at a time, you might think, well, days are continuous as well. So let's try transition time again. And you will end up with this animation. And you might think that something is broken. This is an animation. There's just nothing in there. But then when you think about it, transition time will cut up your data into the different time slots that you have. And you have one measurement per time. And you're trying to draw a line with one measurement, which results in no line. So of course, nothing gets drawn. And then you might think, wait, there's a use case for shadows, because that gives you memory. So we'll add shadow mark, which kind of keeps the old raw data there.
And we get this, which, again, you might be at the point where you say, well, this is really a one-trick pony. Can't really do what I want it to do. The thing is that it's actually doing what it should be doing. What you might fail to grasp, because it's a quite complicated thing, is that, well, shadows don't really combine the old data with the new data. So it is cutting things up. But it's just, again, drawing a lot of one-point lines here. The shadow data never connects itself with the old data, for good reasons, because it's not what it's meant to do.
So what you really want here is another transition, because this is a completely different way of making animation. And I have a transition just for that, which is the transition reveal. And what we see is it's actually doing what we wanted it to do.
What this transition also allows you to do is to add other things and lines. And it will try to interpret that in a nice sense. So if you add the same data, just as geom points, you will, as you probably expect, have a point that traces the frontier of the animation. What you don't usually have with geom points is that I'm specifying a group aesthetic here. That's not something that you usually do for points. But the group aesthetic in gganimate has been given an additional purpose in defining the permanence of objects across frames. So you need that to say, well, this point is the same, and you need to trace it over.
What happens if you give it a unique group? Well, then it doesn't really get combined across the frames. It will just kind of appear there. Lastly, we can do other kinds of visualization here. I do a geom smooth. If you need to animate that, you can no longer reference the weekday, because the statistic transformations that you've done make the weekday disappear at the moment that you're doing the animation. But in the same way as you can reference statistically computed values during aesthetics, you can also do that in transition reveal. And we'll just say, wait until you've done the statistics transformation, and then grab the x value that comes out of geom smooth. And we can again do this.
Earthquake data and enter/exit modifications
I'm running low on time, so I'll just jump onto a happy little data set of earthquakes. What the? This has nothing to do with the quality of gganimate, I must say. This is purely Keynote's fault. So I've just made a bar plot. And again, if you want to animate that, we can make the bars appear one month again.
And we do that with transition states, January, February, and so on. You could consider them as continuous variables, but here in the sense that they are ordered factors. So we're using a discrete scale, which is transition states. And we add shadow markers we have seen before, because we want the old month data to stay there. And we can see we get what we expected. What we might think is a bit crude is that they just pop out of nowhere. It's not nearly as smooth as you might want to have it. And what we can do about this is a new concept that I haven't really talked about before, something called entering and exit modifications. So here we are adding something called enter grow. And this will simply just say when something new pops up, let it grow. So you can actually add flourish like this. And it allows the animation to appear much more smoothly. And gganimate comes with a number of these different entering and exit transitions, or entering and exit modifications. And you can combine them. So you can actually like enter grow and enter fade, and it will do both of these at the same time. So you can do quite a lot with the build-in stuff, like so.
So I guess this is the last slide. I made it in time. So there will be time for questions while Hadley melts away. Thank you for your attention.
Q&A
So I think we have time for one question. And then if you have more questions for Thomas, he's happy to stay here for the rest of his life.
Hey, great talk. Thank you. How does gganimate handle gaps in the data? In all of the examples that you had, you had uniform periods between data. How does it handle something that has holes in it?
Well, great question. So I didn't show all the different transitions. There is quite a lot, because there's quite a lot of different ways to interpret data in a time sense. So with transition time, it kind of looks at the data as key frames. So if some data disappear, it will be considered disappearing, and it will be removed. But sometimes you want it to kind of just drift over to the next position. Transition component is for when you have these non-key frame setups where each element moves based on its own time points. So you can absolutely do that. I just didn't show it.

