Cómo crear 'Warming Stripes' in R
Este año se hicieron muy famosos en todo el mundo los llamados warming stripes, las tiras del calentamiento global, que fueron creadas por el científico Ed Hawkins de la Universidad de Reading. Estos gráficos representan y comunican el cambio climático de una forma muy ilustrativa y eficaz.
Visualising global temperature change since records began in 1850. Versions for USA, central England & Toronto available too: https://t.co/H5Hv9YgZ7v pic.twitter.com/YMzdySrr3A
— Ed Hawkins (@ed_hawkins) May 23, 2018
A partir de su idea, creé tiras para ejemplos de España, como el siguiente de Madrid.
#Temperatura anual en #MadridRetiro desde 1920 a 2017. #CambioClimatico #dataviz #ggplot2 (idea de @ed_hawkins 🙏) @Divulgameteo @edupenabad @climayagua @ClimaGroupUB @4gotas_com pic.twitter.com/wmLb5uczpT
— Dr. Dominic Royé (@dr_xeo) June 2, 2018
En este post voy a enseñar cómo se pueden crear estas tiras en R con el paquete ggplot2. Aunque debo decir que existen muchos caminos en R que nos pueden llevar al mismo resultado o a uno similar, incluso dentro de ggplot2.
Datos
En este caso usaremos las temperaturas anuales de Lisboa del GISS Surface Temperature Analysis que comprenden el periodo 1880-2018. Se trata de series temporales homogeneizadas. También se podrían usar temperaturas mensuales u otras series temporales. El archivo se puede descargar aquí. Lo primero que debemos hacer, siempre y cuando no lo hayamos hecho, es instalar la colección de paquetes tidyverse que incluyen también ggplot2. Además, nos hará falta el paquete lubridate para el tratamiento de fechas. Después, importamos los datos de Lisboa que están en formato csv.
#instalamos los paquetes lubridate y tidyverse
if(!require("lubridate")) install.packages("lubridate")
if(!require("tidyverse")) install.packages("tidyverse")
#paquetes
library(tidyverse)
library(lubridate)
library(RColorBrewer)
#importar las temperaturas anuales
temp_lisboa <- read_csv("temp_lisboa.csv")
str(temp_lisboa)
## spec_tbl_df [139 x 18] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ YEAR : num [1:139] 1880 1881 1882 1883 1884 ...
## $ JAN : num [1:139] 9.17 11.37 10.07 10.86 11.16 ...
## $ FEB : num [1:139] 12 11.8 11.9 11.5 10.6 ...
## $ MAR : num [1:139] 13.6 14.1 13.5 10.5 12.4 ...
## $ APR : num [1:139] 13.1 14.4 14 13.8 12.2 ...
## $ MAY : num [1:139] 15.7 17.3 15.6 14.6 16.4 ...
## $ JUN : num [1:139] 17 19.2 17.9 17.2 19.1 ...
## $ JUL : num [1:139] 19.1 21.8 20.3 19.5 21.4 ...
## $ AUG : num [1:139] 20.6 23.5 21 21.6 22.4 ...
## $ SEP : num [1:139] 20.7 20 18 18.8 19.5 ...
## $ OCT : num [1:139] 17.9 16.3 16.4 15.8 16.4 ...
## $ NOV : num [1:139] 12.5 14.7 13.7 13.5 12.5 ...
## $ DEC : num [1:139] 11.07 9.97 10.66 9.46 10.25 ...
## $ D-J-F : num [1:139] 10.7 11.4 10.6 11 10.4 ...
## $ M-A-M : num [1:139] 14.1 15.2 14.3 12.9 13.6 ...
## $ J-J-A : num [1:139] 18.9 21.5 19.7 19.4 20.9 ...
## $ S-O-N : num [1:139] 17 17 16 16 16.1 ...
## $ metANN: num [1:139] 15.2 16.3 15.2 14.8 15.3 ...
## - attr(*, "spec")=
## .. cols(
## .. YEAR = col_double(),
## .. JAN = col_double(),
## .. FEB = col_double(),
## .. MAR = col_double(),
## .. APR = col_double(),
## .. MAY = col_double(),
## .. JUN = col_double(),
## .. JUL = col_double(),
## .. AUG = col_double(),
## .. SEP = col_double(),
## .. OCT = col_double(),
## .. NOV = col_double(),
## .. DEC = col_double(),
## .. `D-J-F` = col_double(),
## .. `M-A-M` = col_double(),
## .. `J-J-A` = col_double(),
## .. `S-O-N` = col_double(),
## .. metANN = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Vemos en las columnas que tenemos valores mensuales y estacionales, y el valor anual. Pero antes de proceder a visualizar la temperatura anual, debemos sustituir los valores ausentes 999.9 por NA
, usando la función ifelse( )
que lleva una condición y los argumentos correspondientes a verdadero y falso de la condición dada.
#selecionamos la columna del año y la temperatura anual
temp_lisboa_yr <- select(temp_lisboa, YEAR, metANN)
#cambiamos el nombre de la columna
temp_lisboa_yr <- rename(temp_lisboa_yr, ta = metANN)
#valores ausentes 999.9
summary(temp_lisboa_yr)
## YEAR ta
## Min. :1880 Min. : 14.53
## 1st Qu.:1914 1st Qu.: 15.65
## Median :1949 Median : 16.11
## Mean :1949 Mean : 37.38
## 3rd Qu.:1984 3rd Qu.: 16.70
## Max. :2018 Max. :999.90
temp_lisboa_yr <- mutate(temp_lisboa_yr, ta = ifelse(ta == 999.9, NA, ta))
Cuando usamos el año como variable, no solemos convertirlo en un objeto de fecha, no obstante es aconsejable. De este modo nos permite usar las funciones de fechas del paquete lubridate y las funciones de apoyo dentro de ggplot2. La función str_c( )
del paquete stringr, forma parte de la colección de tidyverse, es similar a paste( )
de R Base que nos permite combinar caracteres especificando un separador (sep=“-”). La función ymd( )
(year month day) del paquete lubridate convierte una fecha en un objeto Date. Es posible combinar varias funciones
haciendo uso del pipe operator %>%
que ayuda a encadenar sin asignar el resultado a un nuevo objeto. Su uso es muy extendido especialmente con el paquete tidyverse. Si quieres saber más de su uso, aquí tienes un tutorial.
temp_lisboa_yr <- mutate(temp_lisboa_yr, date = str_c(YEAR, "01-01", sep = "-") %>% ymd())
Creando las tiras
Primero, creamos el estilo del gráfico, especificando todo los argumentos del aspecto que queremos ajustar. Partimos del estilo por defecto de theme_minimal( )
. Además, asignamos
los colores procedientes de RColorBrewer a un objeto col_srip. Más información sobre los colores usados aquí.
theme_strip <- theme_minimal()+
theme(axis.text.y = element_blank(),
axis.line.y = element_blank(),
axis.title = element_blank(),
panel.grid.major = element_blank(),
legend.title = element_blank(),
axis.text.x = element_text(vjust = 3),
panel.grid.minor = element_blank(),
plot.title = element_text(size = 14, face = "bold")
)
col_strip <- brewer.pal(11, "RdBu")
brewer.pal.info
## maxcolors category colorblind
## BrBG 11 div TRUE
## PiYG 11 div TRUE
## PRGn 11 div TRUE
## PuOr 11 div TRUE
## RdBu 11 div TRUE
## RdGy 11 div FALSE
## RdYlBu 11 div TRUE
## RdYlGn 11 div FALSE
## Spectral 11 div FALSE
## Accent 8 qual FALSE
## Dark2 8 qual TRUE
## Paired 12 qual TRUE
## Pastel1 9 qual FALSE
## Pastel2 8 qual FALSE
## Set1 9 qual FALSE
## Set2 8 qual TRUE
## Set3 12 qual FALSE
## Blues 9 seq TRUE
## BuGn 9 seq TRUE
## BuPu 9 seq TRUE
## GnBu 9 seq TRUE
## Greens 9 seq TRUE
## Greys 9 seq TRUE
## Oranges 9 seq TRUE
## OrRd 9 seq TRUE
## PuBu 9 seq TRUE
## PuBuGn 9 seq TRUE
## PuRd 9 seq TRUE
## Purples 9 seq TRUE
## RdPu 9 seq TRUE
## Reds 9 seq TRUE
## YlGn 9 seq TRUE
## YlGnBu 9 seq TRUE
## YlOrBr 9 seq TRUE
## YlOrRd 9 seq TRUE
Para el gráfico final usamos la geometría geom_tile( )
. Como los datos no tienen un valor específico para el eje Y, usamos un valor dummy, aquí es 1. Además, ajusto el ancho de la barra de colores en la leyenda.
ggplot(temp_lisboa_yr,
aes(x = date, y = 1,fill = ta))+
geom_tile()+
scale_x_date(date_breaks = "6 years",
date_labels = "%Y",
expand = c(0, 0))+
scale_y_continuous(expand = c(0, 0))+
scale_fill_gradientn(colors = rev(col_strip))+
guides(fill = guide_colorbar(barwidth = 1))+
labs(title = "LISBOA 1880-2018",
caption = "Datos: GISS Surface Temperature Analysis")+
theme_strip
En el caso de que quisieramos obtener únicamente las tiras, podemos usar theme_void( )
y el argumento show.legend=FALSE en geom_tile( )
para eliminar todos los elementos de estilo. También podemos cambiar el color para los valores NA
, incluyendo el argumento na.value=“grey70” en la función scale_fill_gradientn( )
.
ggplot(temp_lisboa_yr,
aes(x = date, y = 1, fill = ta))+
geom_tile(show.legend = FALSE)+
scale_x_date(date_breaks = "6 years",
date_labels = "%Y",
expand = c(0, 0))+
scale_y_discrete(expand = c(0, 0))+
scale_fill_gradientn(colors = rev(col_strip))+
theme_void()