Search code examples
rggplot2gganimate

geom_density_2d_filled and gganimate: cumulative 2D density estimate animation over time?


This is a follow-up question of sorts to ggplot2 stat_density_2d: how to fix polygon errors at the dataset bounding box edges?

I am trying to animate a 2D density estimate ggplot2::geom_density_2d_filled over time so that each frame adds data to what was presented before. So far I have the gganimate animation working for the 2D density estimate so that each point in time (the dataframe column monthly) is individual, but I have no idea how to proceed from here.

Is it possible to use gganimate to cumulatively animate geom_density_2d_filled? Or could this be achieved by manipulating the source dataframe somehow?

Please see my code below:

library(dplyr)
library(sf)
library(geofi)
library(ggplot2)
library(gganimate)

# Finland municipalities
muns <- geofi::get_municipalities(year = 2022)

# Create sample points
points <- sf::st_sample(muns, 240) %>% as.data.frame()
points[c("x", "y")] <- sf::st_coordinates(points$geometry)
monthly <- seq(as.Date("2020/1/1"), by = "month", length.out = 24) %>%
  rep(., each = 10)
points$monthly <- monthly

p <- ggplot() +
  geom_density_2d_filled(data = points, 
                         aes(x = x, y = y, alpha = after_stat(level))) +
  geom_sf(data = muns, 
          fill = NA, 
          color = "black") +
  coord_sf(default_crs = sf::st_crs(3067)) +
  geom_point(data = points, 
             aes(x = x, y = y), 
             alpha = 0.1) +
  scale_alpha_manual(values = c(0, rep(0.75, 13)), 
                     guide = "none") +
  # gganimate specific
  transition_states(monthly, 
                    transition_length = 1, 
                    state_length = 40) +
  labs(title = "Month: {closest_state}") + 
  ease_aes("linear")

animate(p, renderer = gganimate::gifski_renderer())
gganimate::anim_save(filename = "so.gif", path = "anim")

The resulting animation is seen below. Could this be portrayed cumulatively?

gganimate animation with all frames being a clean slate


Solution

  • To get cumulative figures the easiest way is to repeat each month's data in future months.

    Using the tidyverse, add the following statement before you define p...

    points <- points %>% 
      mutate(monthly = map(monthly, ~seq(., max(monthly), by = "month"))) %>% 
      unnest(monthly)
    

    Note that a cumulative density will not necessarily increase over time - if you want an animation that steadily increases you might want to add contour_var = "count" to your geom_density... term.