Last active
July 16, 2022 21:36
-
-
Save padpadpadpad/b431a160da6a5f8356e1b4528d973b2f 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
# try and recreate famous Ed Hawkins climate change spiral graphic in R and ggplot2 | |
# load packages | |
library(tidyverse) | |
library(MetBrewer) | |
library(gganimate) | |
# load in dataset from NASA | |
d <- read.csv('https://data.giss.nasa.gov/gistemp/tabledata_v4/GLB.Ts+dSST.csv', skip = 1) | |
head(d) | |
# make all columns numeric - there are some *** that i dont know what they mean | |
d <- mutate(d, across(everything(), as.numeric)) | |
# replace NAs with 0 - just make them to have no positive or negative anomaly | |
d <- mutate(d, across(everything(), replace_na, 0)) | |
# tidy the dataframe | |
d <- janitor::clean_names(d) %>% | |
pivot_longer(cols = jan:dec, names_to = 'month', values_to = 'anomaly') | |
# add a time column | |
d <- mutate(d, time = paste(year, toupper(month), sep = '-'), | |
time = lubridate::ym(time), | |
month2 = lubridate::month(time)) | |
# create first plot | |
p1 <- ggplot(d, aes(month2, anomaly, col = anomaly)) + | |
geom_line(aes(group = year)) + | |
scale_color_gradientn('Temperature anomaly', colors = met.brewer(name='Homer1', direction=-1, override.order = F)) + | |
MicrobioUoE::theme_black() + | |
theme(panel.grid.major = element_blank(), | |
axis.title.x = element_blank()) + | |
scale_x_continuous(breaks = 1:12, labels = c('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) | |
p1 + coord_polar() | |
# want to convert polar coordinates to cartesian to allow animation to go from December back to January | |
# using this link https://stackoverflow.com/questions/55132352/geom-path-refuses-to-cross-over-the-0-360-line-in-coord-polar | |
angles <- tibble(month = unique(d$month), | |
angle = seq(15, by = 30, length.out = 12)) | |
d <- left_join(d, angles) | |
head(d) | |
# remove 2022 because its mid year | |
d <- filter(d, year < 2022) | |
# add buffer to make everything positive | |
buffer <- 3 | |
d <- mutate(d, x_anomaly = sin(pi * angle/180) * (anomaly + buffer), | |
y_anomaly = cos(pi * angle/180) * (anomaly + buffer)) | |
# create limits | |
limits <- c(-(max(d$anomaly) + buffer), max(d$anomaly) + buffer) | |
# create circles for some temperatures | |
circles <- data.frame( | |
r = c(buffer, buffer + 1, buffer - 1)) %>% | |
mutate(r = round(r, 0), | |
x0 = 0, | |
y0 = 0, | |
label = c('0ºC', '+1ºC', '-1ºC')) | |
# add months | |
months <- mutate(angles, anomaly = limits[2] + limits[2] * .1, | |
x_anomaly = sin(pi * angle/180) * anomaly, | |
y_anomaly = cos(pi * angle/180) * anomaly) | |
# increase limits slightly | |
limits <- limits + limits*.1 | |
# create base plot | |
p1 <- ggplot(d, aes(x_anomaly, y_anomaly)) + | |
scale_x_continuous(limits = limits) + | |
scale_y_continuous(limits = limits) + | |
ggforce::theme_no_axes() + | |
theme(panel.background = element_rect(fill = 'black'), | |
legend.position = 'none') + | |
ggforce::geom_circle(aes(x0 = x0, y0 = y0, r = r), fill = NA, data = circles, inherit.aes = FALSE,col = 'white', size = 1.2) + | |
geom_text(aes(x_anomaly, y_anomaly, label = month), data = months, col = 'white', size = MicrobioUoE::pts(14)) + | |
geom_path(aes(col = anomaly), alpha = 0.9) + | |
geom_label(aes(x0, r, label = label), circles, fill = 'white', size = MicrobioUoE::pts(14)) + | |
coord_equal() + | |
transition_reveal(time) + | |
scale_color_gradientn('Temperature anomaly', colors = met.brewer(name='Homer1', direction=-1, override.order = F)) + | |
geom_text(aes(x = 0, y = 0, label = year, col = anomaly), size = MicrobioUoE::pts(24)) | |
# save out the animation | |
gganimate::animate(p2, fps = 10, nframes = 120, duration = 60, width = 4, height = 4.5, units = 'in', renderer = av_renderer(), res = 150) | |
anim_save('~/climate_spiral.mp4', animation = last_animation()) | |
gganimate::animate(p1, fps = 10, nframes = 120, duration = 60, width = 4, height = 4.5, units = 'in', res = 150) | |
anim_save('~/climate_spiral.gif', animation = last_animation()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment