This year, the so-called warming stripes, which were created by the scientist Ed Hawkins of the University of Reading, became very famous all over the world. These graphs represent and communicate climate change in a very illustrative and effective way.
In this post I will show how you can create these strips in R with the ggplot2 library. Although I must say that there are many ways in R that can lead us to the same result or to a similar one, even within ggplot2.
Data
In this case we will use the annual temperatures of Lisbon GISS Surface Temperature Analysis, homogenized time series, comprising the period from 1880 to 2018. Monthly temperatures or other time series could also be used. The file can be downloaded here. First, we should, as long as we have not done it, install the collection of tidyverse packages that also include ggplot2. Then, we import the data of Lisbon in csv format.
spc_tbl_ [139 × 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>
We see in the columns that we have monthly and seasonal values, and the annual temperature value. But before proceeding to visualize the annual temperature, we must replace the missing values 999.9 with NA, using the ifelse( ) function that evaluates a condition and perform the given argument corresponding to true and false.
# select only the annual temperature and year columntemp_lisboa_yr<-select(temp_lisboa, YEAR, ta =metANN)# missing values 999.9summary(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))
When we use the year as a variable, we do not usually convert it into a date object, however it is advisable. This allows us to use the date functions of the lubridate package and the support functions inside of ggplot2. The str_c( ) function of the library stringr, part of the collection of tidyverse, is similar to paste( ) of R Base that allows us to combine characters by specifying a separator (sep = “-”). The ymd( ) (year month day) function of the lubridate package converts a date character into a Date object. It is possible to combine several functions using the pipe operator%>% or |> that helps to chain without assigning the result to a new object. The first pipe in R was %>% very extended especially within the tidyverse package collection. If you want to know more about its use, you can find here a tutorial or some details on differences between both here.
temp_lisboa_yr<-mutate(temp_lisboa_yr, date =make_date(YEAR))
Creating the strips
First, we create the style of the graph, specifying all the arguments of the theme we want to adjust. We start with the default style of theme_minimal( ). In addition, we assign the colors from RColorBrewer to an object col_srip. More information about the colors used here.
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
For the final graphic we use the geometry geom_tile( ). Since the data does not have a specific value for the Y axis, we need a dummy value, here I used 1. Also, I adjust the width of the color bar in the legend.
maxmin<-range(temp_lisboa_yr$ta, na.rm =T)md<-mean(temp_lisboa_yr$ta, na.rm =T)ggplot(temp_lisboa_yr,aes(date, y =1, fill =ta))+geom_tile()+scale_x_date( date_breaks ="6 years", date_labels ="%Y", expand =c(0, 0))+scale_fill_gradientn(colors =rev(col_strip), values =scales::rescale(c(maxmin[1], md, maxmin[2])), na.value ="gray80")+labs( title ="LISBOA 1880-2018", caption ="Datos: GISS Surface Temperature Analysis")+coord_cartesian(expand =FALSE)+theme_strip()
In case we want to get only the strips, we can use theme_void( ) and the argument show.legend = FALSE in geom_tile( ) to remove all style elements. We can also change the color for the NA values, including the argument na.value = “gray70” in the scale_fill_gradientn( ) function.