Created
January 11, 2022 19:17
-
-
Save favstats/a5b3f246b5e59a0a15ecde4e52a36287 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Create NYT Spiral Animations | |
## Most Code comes from here: https://bydata.github.io/nyt-corona-spiral-chart/ | |
library(tidyverse) | |
library(lubridate) | |
library(gganimate) | |
library(viridis) | |
owid_url <- "https://github.com/owid/covid-19-data/blob/master/public/data/owid-covid-data.csv?raw=true" | |
covid <- read_csv(owid_url) | |
first_rows <- covid %>% | |
distinct(location) %>% | |
mutate(date = as_date("2020-01-01"), | |
new_cases = 0, | |
new_cases_smoothed = 0, | |
new_cases_per_million = 0, | |
new_cases_smoothed_per_million = 0, | |
new_deaths = 0, | |
new_deaths_smoothed = 0, | |
new_deaths_per_million = 0, | |
new_deaths_smoothed_per_million = 0) | |
covid_cases <- covid %>% | |
select(date, | |
new_cases, | |
new_cases_smoothed, | |
new_deaths, | |
new_deaths_smoothed, | |
new_cases_per_million, | |
new_cases_smoothed_per_million, | |
new_deaths_per_million, | |
new_deaths_smoothed_per_million, | |
location) %>% | |
# Add the dates before the 1st confirmed case | |
bind_rows(first_rows) %>% | |
arrange(date) %>% | |
group_by(location) %>% | |
complete(date = seq(min(.$date), max(.$date), by = 1), | |
fill = list(new_cases = 0, | |
new_cases_smoothed = 0, | |
new_cases_per_million = 0, | |
new_cases_smoothed_per_million = 0, | |
new_deaths = 0, | |
new_deaths_smoothed = 0, | |
new_deaths_per_million = 0, | |
new_deaths_smoothed_per_million = 0)) %>% | |
mutate(day_of_year = yday(date), | |
year = year(date) | |
) %>% | |
ungroup() %>% | |
# 2020 is a leap year, we could drop Feb 29, 2020 for the sake of 365-day years | |
filter(date != as_date("2020-02-29")) %>% | |
group_by(year, location) %>% | |
mutate(day_of_year = row_number()) %>% | |
ungroup() | |
saveRDS(covid_cases, file = "data/covid_cases.rds") | |
##### plot ##### | |
size_factor <- 12000 | |
# Colors | |
outline_color <- "#D97C86" | |
fill_color <- "#F0C0C1" | |
base_grey <- "grey28" | |
month_length <- c(31, 28, 31, 30, 31, 30, | |
31, 31, 30, 31, 30, 31) | |
month_breaks <- cumsum(month_length) - 30 | |
p <- covid_cases %>% | |
mutate(date2 = date) %>% | |
filter(location == "Netherlands") %>% | |
ggplot() + | |
## I am plotting a ton of lines here because geom_linerange doesn't seem to work | |
## properly with gganimate | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date), | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.9, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.8, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.70, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.6, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.5, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.4, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.3, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.2, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) - new_cases_smoothed_per_million * size_factor * 0.1, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.9, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.8, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.70, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.6, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.5, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.4, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.3, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.2, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
geom_line(aes(x = day_of_year, | |
y = as.POSIXct(date) + new_cases_smoothed_per_million * size_factor * 0.1, | |
group = year, color = new_cases_smoothed_per_million), | |
width = 0, | |
# color = outline_color, | |
size=1.75, | |
show.legend = T) + | |
# annotate("text", label = paste0(year_annotations$year, "\u2192"), x = year_annotations$x, | |
# y = year_annotations$y, | |
# family = "Arial", | |
# size = 1, vjust = 1.3, hjust = 0.15) + | |
# basic line | |
scale_x_continuous(minor_breaks = month_breaks, | |
breaks = month_breaks, | |
labels = c("Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."), | |
limits = c(1, 365), | |
expand = c(0, 0) | |
) + | |
#' set the lower limit of the y-axis to a date before 2020 | |
#' so that the spiral does not start in the center point | |
scale_y_continuous(limits = c(as.POSIXct("2019-07-01"), NA), | |
expand = c(0, 0)) + | |
coord_polar() + | |
theme_void() + | |
labs(title = "COVID-19 in the Netherlands", | |
subtitle="7-day Average COVID cases per illion people\n", | |
caption="Data: Our World in Data | Inspired by: NYT | Initial Code: Ansgar Wolsing (@_ansgar) | Animation: Fabio Votta (@favstats)") + | |
theme( | |
legend.position = "bottom", | |
plot.title = element_text(hjust = 0.5, size = 16), | |
plot.subtitle = element_text(hjust = 0.5, size = 7), | |
plot.caption = element_text(hjust = 1, size = 3.5), | |
plot.background = element_rect(color = NA, fill = "white"), | |
panel.grid.major.x = element_line(color = "grey70", size = 0.2, linetype = "dotted"), | |
panel.grid.minor.x = element_line(color = "grey70", size = 0.2, linetype = "dotted"), | |
axis.text.x = element_text(color = base_grey, size = 5, hjust = 0.5) | |
) + | |
viridis::scale_color_viridis(option = "rocket", direction = -1) + | |
guides(color = guide_colourbar(title = "7-day Average COVID cases per million", | |
title.vjust = 1, | |
title.theme = element_text(size = 6.5), | |
label.theme = element_text(size = 3.5), | |
barwidth = 5, barheight = 0.5)) + | |
transition_reveal(date) + | |
ease_aes('linear') | |
p <- p %>% | |
animate(nframes = 300, fps = 20, #duration = 25, | |
width = 1000, height = 1000, | |
res = 300, end_pause = 60) | |
anim_save("netherlands.gif", animation = p) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment