Nick
Nick

Reputation: 297

How can I animate points on a spatial map with gganimate, sf, and ggplot2?

I'm having some trouble with animating some points on a spatial map. For some reason, only about half of the points show up in the animation. In the static plot, I can clearly see all the points.

How can I make sure that the gganimation shows all the points? Does gganimate not 'play nicely' with spatial maps?

Does anyone have more experience with using gganimate and spatial plotting? I can reproduce the problem with an example dataset:

    library(sf)
    library(ggplot2)
    library(ggspatial)
    library(gganimate)

##Reading example data
    nc <- st_read(system.file("shape/nc.shp", package="sf"))

##Create new sf=variable of random points
    A <- nc %>% 
      st_sample(size = 30) %>% 
      st_coordinates() %>%
      as.data.frame()

##Create static map
    B <- ggplot() +
      annotation_spatial(data=nc) +
      geom_point(data = A, aes(x=X, y=Y), size = 2, col = "#3a6589")

##Create animation with points showing up one by one
    plot_anim <- B +
      transition_states(states = Y, state_length = 0, wrap = FALSE) +
      enter_recolor(fill = "#f0f5f9") +
      shadow_mark(past = TRUE, alpha = 1, fill = "#3a6589")

##Render animation
    animate(plot_anim, fps = 40, end_pause = 60)

Upvotes: 2

Views: 3391

Answers (1)

Jindra Lacko
Jindra Lacko

Reputation: 8739

I suggest to plot your points via ggplot2::geom_sf() - I have found it reliable in animating spatial data.

See the slightly amended code below; what I have done is:

  • kept the A object in sf format
  • created a technical variable Y with the second(= Y) coordinate; it is then used as in your original code
  • removed the ggspatial dependency, and reframed your static map call
  • removed the fps = 40 (this should have no effect except file size); we need less than 2 MB to upload here

You may find you need to install {transformr} to animate sf objects; it should not be a showstopper.

library(sf)
library(ggplot2)
library(gganimate)

##Reading example data
nc <- st_read(system.file("shape/nc.shp", package="sf"))

##Create new sf=variable of random points
A <- nc %>% 
  st_sample(size = 30) %>% 
  st_as_sf() %>% 
  dplyr::mutate(Y = st_coordinates(.)[,2])

##Create static map
B <- ggplot() +
  geom_sf(data = nc) +
  geom_sf(data = A, size = 2, col = "#3a6589")

# save static map
ggsave("static_map.png")

##Create animation with points showing up one by one
plot_anim <- B +
  transition_states(states = Y, state_length = 0, wrap = FALSE) +
  enter_recolor(fill = "#f0f5f9") +
  shadow_mark(past = TRUE, alpha = 1, fill = "#3a6589")

##Render animation
animate(plot_anim, end_pause = 60,
        height = 200, width = 400) # a higher res img would not upload here :(

# save animated map
anim_save("animated_map.gif")

The static map / 30 random NC points

a static map of NC

The dynamic map / small (because 2 MB upload requirements) but otherwise looks legit to me...

a dynamic map of NC

Upvotes: 4

Related Questions