Say that I have these data. One for shading counties of a state and the other for plotting points.
library(tidyverse)
library(gganimate)
devtools::install_github("UrbanInstitute/urbnmapr")
library(urbanmapr)
#1. counties dataset for the shading of the background
data(counties)
#keep only Texas counties
counties <- filter(counties, state_fips==48)
#2. dots dataset for dots over time
dots <- data.frame(group = c(rep(1,3), rep(2,3)),
lat = c(rep(32, 3), rep(33, 3)),
long = c(rep(-100, 3), rep(-99,3)),
year = c(1:3, 1:3))
I then plot them (first not using gganimate
):
ggplot() +
geom_polygon(data = counties, aes(long, lat, group = county_fips, fill = as.numeric(county_fips))) +
scale_fill_gradient(low = "navy", high = "lightskyblue3") +
geom_point(data = dots, aes(long, lat, group=interaction(long, lat), color=year),
size=6, show.legend = FALSE) +
theme_bw() +
scale_color_gradientn(colours = c("red", "yellow", "darkgreen")) +
coord_map() +
labs(subtitle = paste('Year: {frame_time}')) +
theme(plot.subtitle = element_text(hjust = 0.8, vjust=-10, size=30)) +
theme(panel.background = element_rect(fill = 'white')) +
theme(panel.grid = element_blank(),axis.title = element_blank(),
axis.text = element_blank(),axis.ticks = element_blank(),
panel.border = element_blank())+
theme(legend.position = c(0.15, .15)) +
theme(legend.key.size = unit(2,"line"),legend.title=element_text(size=16),
legend.text=element_text(size=14)) +
labs(fill = "abc")
Here is the result:
The problem comes in when I try to animate the dots using gganimate
:
map <- ggplot() +
geom_polygon(data = counties, aes(long, lat, group = county_fips, fill = as.numeric(county_fips))) +
scale_fill_gradient(low = "navy", high = "lightskyblue3") +
geom_point(data = dots, aes(long, lat, group=interaction(long, lat), color=year),
size=6, show.legend = FALSE) +
theme_bw() +
scale_color_gradientn(colours = c("red", "yellow", "darkgreen")) +
coord_map() +
labs(subtitle = paste('Year: {frame_time}')) +
theme(plot.subtitle = element_text(hjust = 0.8, vjust=-10, size=30)) +
theme(panel.background = element_rect(fill = 'white')) +
theme(panel.grid = element_blank(),axis.title = element_blank(),
axis.text = element_blank(),axis.ticks = element_blank(),
panel.border = element_blank())+
theme(legend.position = c(0.15, .15)) +
theme(legend.key.size = unit(2,"line"),legend.title=element_text(size=16),
legend.text=element_text(size=14)) +
labs(fill = "abc") +
transition_time(year) +
shadow_mark(size=6)
anim_save("output/test.gif", map, end_pause=6, width = 800, height = 800, duration=8)
Note that it is exactly the same except for the transition_time
and shadow_mark
lines. Here is the result:
The background colors are VERY different. It might be the case that the colors are reversed or something; I am not sure. However, in my real example using many more dots and different values for the shading, the shading has little if any resemblance to the actual data. What in the world is going on and how can I fix it?
I'm not sure what exactly the problem is, but polygons can be problematic, because they tend to violate the tidy data rule of "one row per observation". Also, as a general principle, I would recommend using geom_sf()
whenever you're working with geospatial data. Below is code that reproduces your animation using geom_sf()
.
In theory, I should have been able to plot the points with geom_sf()
as well, but I ran into another issue that looks like a bug with gganimate, so I had to work around and extract the projected coordinates for the points and plot with geom_point()
.
library(tidyverse)
library(gganimate)
library(sf)
#> Linking to GEOS 3.7.2, GDAL 2.4.2, PROJ 5.2.0
# 1. get shape files for texas
library(tidycensus)
options(tigris_use_cache = TRUE)
# download counties for Texas
counties <- get_acs(
state = 48, # omit to download all US counties
geography = "county", year = 2015, geometry = TRUE,
variables = "B19013_001" # need to specify some variable to download, here median income
)
#> Getting data from the 2011-2015 5-year ACS
# 2. dots dataset for dots over time
dots <- data.frame(
group = c(rep(1,3), rep(2,3)),
lat = c(rep(32, 3), rep(33, 3)),
long = c(rep(-100, 3), rep(-99,3)),
year = c(1:3, 1:3)
)
# add geometry column
dots_sf <- dots %>%
mutate(
geometry = st_sfc(
map2(lat, long, function(lat, long) st_point(x = c(long, lat))),
crs = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
) %>%
st_transform(crs = 3083) # CRS appropriate for Texas, https://epsg.io/3083
) %>%
st_as_sf()
# and extract transformed coords
dots_sf_transf <- dots_sf %>%
mutate(
long_transf = map_dbl(geometry, function(x) x[[1]]),
lat_transf = map_dbl(geometry, function(x) x[[2]])
)
# 3. static plot
p <- ggplot() +
geom_sf(data = counties, aes(fill = as.numeric(GEOID))) +
scale_fill_gradient(low = "navy", high = "lightskyblue3") +
geom_point(
data = dots_sf_transf,
aes(x = long_transf, y = lat_transf, group = group, color = year),
size = 6, show.legend = FALSE
) +
scale_color_gradientn(colours = c("red", "yellow", "darkgreen")) +
coord_sf(crs = 3083) +
labs(subtitle = "Year: {frame_time}", fill = "abc") +
theme_void() +
theme(legend.position = c(0.15, .15))
p
# animation
p + transition_time(year) + shadow_mark(size=12)
Created on 2019-11-03 by the reprex package (v0.3.0)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With