paleolimbot / ggspatial

Enhancing spatial visualization in ggplot2
https://paleolimbot.github.io/ggspatial
368 stars 34 forks source link

Speed up creating gganimations with ggspatial #87

Open idshklein opened 3 years ago

idshklein commented 3 years ago

annotation_map_tile is amazing because it allows the addition of basemaps, without needing a non-fully-ggplot2 syntax as in ggmap. however, when rending an animation with both packages, it seems that ggmap is WAY faster, maybe because it doesn't require the rendering of the basemap each time. Let's take the example from the gganimate wiki:

require(gganimate)
require(tidyverse)
require(lubridate)
require(ggmap)
require(maps)
require(mapdata)

# import data hosted in my github rep. 
typhoon_data <- read.csv("https://raw.github.com/wenlong-liu/typhoon_animation/master/Data/typhoon_doksuri.csv")

# data cleaning.
tracks <-  typhoon_data %>% 
  # reforamt date time using lubridate package. 
  mutate(time = mdy_hm(time)) %>% 
  # rename columns.
  rename(long = lng) 

# draw a base box for maps.
tracks_box <- make_bbox(lon = tracks$long, lat = tracks$lat, f = 0.5)
sq_map <- get_map(location = tracks_box, maptype = "satellite", source = "google", zoom = 5)

# plot map.
ggmap(sq_map) + 
  theme(text = element_text(size = 17))+
  geom_point(data = tracks, mapping = aes(x = long, y = lat, color = pressure)) +
  geom_line(data = tracks, mapping = aes(x = long, y = lat, color = pressure), size = 2) +
  scale_color_continuous(name = "Pressure(hPa)",low = "yellow", high = "red")+
  labs(title = "Tracking of Typhoon Doksuri happened in 2017",
       subtitle = "Time:{frame_along}",
       x = "Long", y = "Lat", 
       caption = "Data Source: jswater.jiangsu.gov.cn")+
  transition_reveal(time)+
  NULL

this takes about 5 seconds.

when trying to recreate with ggspatial (and enjoying much cleaner syntax), it takes about 5 minutes:

#recreate in ggspatial - takes FOREVER
require(ggspatial)
tracks %>% 
  st_as_sf(coords = c("long","lat"),crs = 4326) %>% 
  ggplot() + 
  annotation_map_tile() + 
  geom_point(data = tracks, mapping = aes(x = long, y = lat, color = pressure)) +
  geom_line(data = tracks, mapping = aes(x = long, y = lat, color = pressure), size = 2) +
  scale_color_continuous(name = "Pressure(hPa)",low = "yellow", high = "red")+
  labs(title = "Tracking of Typhoon Doksuri happened in 2017",
       subtitle = "Time:{frame_along}",
       x = "Long", y = "Lat", 
       caption = "Data Source: jswater.jiangsu.gov.cn")+
  transition_reveal(time) 

can this be solved, or that ggmap and ggspatial work in totally different ways regarding rendering?

paleolimbot commented 3 years ago

This is an issue I have as well! I'm not sure how ggmap does its rendering, but I do know that the tile map engine that ggspatial uses is outdated (I wrote it nearly 7 years ago!). I need to update the engine for totally unrelated reasons; however, you could try to pre-cache the image and plot it separately. Here's my hack-job of an example (which takes ~ 45 secs to render).

require(gganimate)
require(tidyverse)
require(lubridate)
require(maps)
require(mapdata)
library(sf)
library(ggspatial)

# import data hosted in my github rep. 
typhoon_data <- read.csv("https://raw.github.com/wenlong-liu/typhoon_animation/master/Data/typhoon_doksuri.csv")

# data cleaning.
tracks <-  typhoon_data %>% 
  # reforamt date time using lubridate package. 
  mutate(time = mdy_hm(time)) %>% 
  # rename columns.
  rename(long = lng) 

track_sf <- tracks %>% 
  st_as_sf(coords = c("long","lat"), crs = 4326)

# pre cache a single image
tracks_box <- sp::bbox(as(track_sf, "Spatial"))
rownames(tracks_box) <- c("x", "y")
img <- rosm::osm.image(tracks_box)
img_box <- attr(img, "bbox")

ggplot(tracks) +
  # annotation_map_tile() + 
  annotation_raster(img, img_box[1], img_box[3], img_box[2], img_box[4], TRUE) +
  geom_spatial_point(data = tracks, mapping = aes(x = long, y = lat, color = pressure)) +
  geom_spatial_path(data = tracks, mapping = aes(x = long, y = lat, color = pressure), size = 2) +
  scale_color_continuous(name = "Pressure(hPa)",low = "yellow", high = "red")+
  labs(title = "Tracking of Typhoon Doksuri happened in 2017",
       subtitle = "Time:{frame_along}",
       x = "Long", y = "Lat", 
       caption = "Data Source: jswater.jiangsu.gov.cn")+
  transition_reveal(time) +
  coord_sf(crs = 3857)