# Making an Animated Contour Plot

By Jake Thompson in R

September 5, 2018

Earlier this week Mike Bostock tweeted a interesting looking contour plot with a link to edit the formula and manipulate the graphic using D3.js.

A live 2D function plot. Edit the function and reply with interesting images! https://t.co/joWfPgUAAU pic.twitter.com/XYhvJBavRM

— Mike Bostock (@mbostock) September 3, 2018

I decided I would attempt to recreate the image using
**ggplot2**, and animate it using the new
**gganimate** package.

## Creating the data

I started by creating a data frame with all the combinations of `x`

and `y`

on a grid between -10 and 10, in intervals of 0.1. Then I defined a third variable, `z`

as a function of `x`

and `y`

, using the same equation as originally used
here.

```
plot_data <- crossing(x = seq(-10, 10, 0.1), y = seq(-10, 10, 0.1)) %>%
mutate(z = sin(sin(x * (sin(y) - cos(x)))) - cos(cos(y * (cos(x) - sin(y)))))
plot_data
#> # A tibble: 40,401 × 3
#> x y z
#> <dbl> <dbl> <dbl>
#> 1 -10 -10 -1.77
#> 2 -10 -9.9 -0.950
#> 3 -10 -9.8 -0.275
#> 4 -10 -9.7 -0.138
#> 5 -10 -9.6 0.0279
#> 6 -10 -9.5 -1.01
#> 7 -10 -9.4 -1.80
#> 8 -10 -9.3 -1.28
#> 9 -10 -9.2 -0.564
#> 10 -10 -9.1 -0.227
#> # … with 40,391 more rows
```

Now we can use that data to make the image!

## Create the plot

To create the plot, we are basically making a heat map of sorts, where the fill is defined by the newly calculated `z`

variable. I use `geom_raster`

because it offers speed improvements over `geom_tile`

when all tiles are the szme size, which they are in this case. Given that we have a lot of tiles, I’ll take the speed!

```
ggplot(plot_data, aes(x = x, y = y)) +
geom_raster(aes(fill = z), interpolate = TRUE, show.legend = FALSE) +
scale_fill_viridis_c(option = "C") +
coord_equal() +
theme_void()
```

Pretty good! But then, Jeff Baumes upped the stakes!

A version enabling "t" in the equation that changes over time for animated plots.https://t.co/atNnAXwhFm pic.twitter.com/mEpbJDTQ8N

— Jeff Baumes (@jeffbaumes) September 4, 2018

Well now I can’t not animate it. So…

## Add time and animate

To create an animated plot, we need a time variable, `t`

. We start by creating a data frame similar to the one we created above. It includes all combinations of `x`

and `y`

from -10 to 10 in increments of 0.1, but now those values are also cross with the time variable, `t`

, which goes from 0 to 5 in increments of 0.1. The `z`

variable, which will still be our fill color, is now a function of `x`

, `y`

, and `t`

, as in
Jeff’s example. Finally, we can use the same **ggplot2** code as above, with the addition of the `transition_time`

function from **gganimate**.

```
t_lookup = data_frame(t = c(seq(0, 5, 0.1), seq(4.9, 0, -0.1)),
t2 = seq(0, 10, 0.1))
plot_data <- crossing(x = seq(-10, 10, 0.1), y = seq(-10, 10, 0.1),
t2 = seq(0, 10, 0.1)) %>%
left_join(t_lookup, by = "t2") %>%
mutate(z = sin(sin(x * (sin(y + t) - cos(x - t)))) - cos(cos(y * (cos(x - t) - sin(y + t)))))
ggplot(plot_data, aes(x = x, y = y)) +
geom_raster(aes(fill = z), interpolate = TRUE, show.legend = FALSE) +
scale_fill_viridis_c(option = "C") +
coord_equal() +
theme_void() +
transition_time(t2)
```

And there we have it! With just one extra variable and one additional line of code for our plot, we have an animated contour plot!