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