0

I'm trying to animate points moving over a map in gganimate. In teh following example, animating just the points works and a static plot of the points and map works, but combining them fails with the error Error in mapply(FUN = f, ..., SIMPLIFY = FALSE) : zero-length inputs cannot be mixed with those of non-zero length

Here's a repro:

Load libraries

# gganimate isn't on CRAN
devtools::install_github('thomasp85/gganimate')
library(tidyverse)
library(gganimate)
library(sf)
# for the spatial data
library(rnaturalearth)             

Create data

# Points data
time <- seq(ISOdate(2015, 6, 1), ISOdate(2015, 8, 1), length.out = 100)
track1 <- tibble(lon = seq(-161, -155, length.out = 100),
                 lat = seq(19, 25, length.out = 100),
                 time = time,
                 trackid = 1)
track2 <- tibble(lon = seq(-155, -161, length.out = 100),
                 lat = seq(19, 25, length.out = 100),
                 time = time,
                 trackid = 2)
d <- rbind(track1, track2)

# Spatial data
earth <- st_as_sf(ne_download(scale = "medium",
                              category = "physical",
                              type = "coastline"))
deg_buff <- 1
lon_range <- range(d$lon) + c(-deg_buff, deg_buff)
lat_range <- range(d$lat) + c(-deg_buff, deg_buff)
bbox <- st_polygon(list(cbind(lon_range[c(1,1,2,2,1)], 
                              lat_range[c(1,2,2,1,1)])))
bbox <- st_sfc(bbox)
st_crs(bbox) <- st_crs(earth)
area <- st_intersection(earth, bbox)

Animate points (works)

p <- ggplot(d, aes(lon, lat)) +
  geom_point() +
  labs(subtitle = 'Date: {format(frame_time, "%b %e")}') +
  transition_components(trackid, time) +
  shadow_trail(distance = 0.01, size = 0.3)
animate(p, 100, 20)

Plot a static map (works)

ggplot(d, aes(lon, lat)) +
  geom_sf(data = area, inherit.aes = FALSE) +
  geom_point()

Animate points with static map in background (fails)

p2 <- ggplot(d, aes(lon, lat)) +
  geom_sf(data = area, inherit.aes = FALSE) +
  geom_point() +
  labs(subtitle = 'Date: {format(frame_time, "%b %e")}') +
  transition_components(trackid, time) +
  shadow_trail(distance = 0.01, size = 0.3)
animate(p2, 100, 20)
Roman
  • 4,744
  • 2
  • 16
  • 58
  • gganimate is not on cran, otherwise a great MWE. Could you add a comment with the devtools::install code? Just as speculation, where do the arguments to transitions_components come from? It seems you would need an sf object with a time series of centering points. – Richard Careaga Nov 12 '18 at 18:27
  • @RichardCareaga Totally forgot gganimate isn't on CRAN - thanks for the reminder! I think the arguments to transition_components are similar to arguments to aes, that is unquoted column names. In transition_components, they're the grouping and timestep variables, respectively. But I don't want the geom_sf to animate. I just want it there in the background. Not sure how to indicate it should be a static layer. – Corned Beef Hash Map Nov 12 '18 at 19:28

2 Answers2

2

1

  1. Moved data = d and aes() from ggplot() to geom_point()
  2. Changed transition_components() to transition_time()
  3. Changed shadow_trail to shadow_wake
  4. (Added color)

Code

p2 <- ggplot() +
    geom_sf(data = area, color = "red") +
    geom_point(data = d, aes(lon, lat), inherit.aes = FALSE) +
    labs(subtitle = 'Date: {format(frame_time, "%b %e")}') +
    transition_time(time) +
    shadow_wake(0.3)

animate(p2, 100)
Roman
  • 4,744
  • 2
  • 16
  • 58
0

trackid is undefined and what throws the error in p2; time is defined.

Richard Careaga
  • 628
  • 1
  • 5
  • 11
  • I'm not sure what you mean. ```trackid``` is defined in ```d```. It's 1 for the first 100 rows and 2 for the second 100 rows. It's undefined in ```area```, but then again so is ```time```. – Corned Beef Hash Map Nov 12 '18 at 22:30
  • Added an answer, b/c that's the only way I've found to do code blocks. When running the example *time* ends up in the namespace because it's globally defined, but *trackid* doesn't; it's local to the *d*, *track1* and *track2* objects. You do call *d* in the initial ggplot() for p2, but then for geom_sf, you use area as the data. d is a tibble and if you want to refer to it's components, you either have to do it explicitly, as in d$trackid or through %>% when you can use the bare name. – Richard Careaga Nov 12 '18 at 23:26
  • I don't think that's correct. ```transition_components``` takes unquoted column names just like ```aes``` in ```ggplot```. Also, if it was a matter of ```trackid``` being undefined then the first animated plot wouldn't work, but this does: p <- ggplot(d, aes(lon, lat)) + geom_point() + labs(subtitle = 'Date: {format(frame_time, "%b %e")}') + transition_components(trackid, time) + shadow_trail(distance = 0.01, size = 0.3) animate(p, 100, 20) – Corned Beef Hash Map Nov 13 '18 at 00:53
  • d in the first animation works because it sets the data and the + arguments don't change it, so there's no need to quote "tracked." "Time" is already global. – Richard Careaga Nov 13 '18 at 21:35