Life (expectancy), animated
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Global socio-economic data is easily accessible nowadays. Just type the indicator of interest and the name of the country in your preferred search engine and you can find its value, sometimes also an additional plot or a map. But what about when you want to go further and (for example):
- Want to compare many countries?
- Get data just for a specific year?
- See changes in time?
- Just want to create a very specific plot or a map?
In this blog post, I will show how to download, process, and present global socio-economic data, using the following packages:
library(wbstats) # the World Bank data downloading library(dplyr) # data manipulation library(tidyr) # data manipulation library(purrr) # data manipulation library(ggplot2) # data visualization library(sf) # spatial data manipulation library(rnaturalearth) # access to spatial data library(tmap) # spatial data visualization
World Bank Data
The World Bank Data is a source of various global socio-economic indicators with a large database of historical records.
Its API is, for instance, accessible through the R package wbstats package.
The two most important functions of this package are wbsearch()
and wb()
.
The first one allows for searching for available indicators, and the second one is used for downloading the data.
Read the vignette “wbstats: An R package for searching and downloading data from the World Bank API” to learn more about this package.
Here, I would like to create a time-series of a selected indicator. The function below downloads data for a given indicator and a year. Secondly, it selects only the variables of interest and reshapes them into the wide format.
wb_data_create = function(indicator, new_name, year, ...){ df = wb(indicator = indicator, startdate = year, enddate = year, ...) %>% select(iso_a2 = iso2c, value, year = date) %>% mutate(indicator = new_name) %>% spread(indicator, value) %>% as_data_frame() # return the dataframe df }
Importantly, this function can be also used to download data from many years using the map_dfr()
function.
As an example, let’s download a data of life expectancy at birth for every five years from 1963 to 2013 on a country level:
data_life_exp = seq(1963, 2013, by = 5) %>% map_dfr(wb_data_create, indicator = "SP.DYN.LE00.IN", new_name = "life_exp", country = "countries_only")
This new dataset, data_life_exp
, already allows analyzing temporal changes in life expectancy.
For example, we can calculate the mean life expectancy of all countries:
data_life_exp_avg = data_life_exp %>% group_by(year) %>% summarise(mean_life_exp = mean(life_exp, na.rm = TRUE))
Let’s visualize the life expectancy. Each grey line represents one country, and the red one shows the mean life expectancy.
ggplot() + geom_line(data = data_life_exp, aes(year, life_exp, group = iso_a2), color = "gray40") + geom_line(data = data_life_exp_avg, aes(year, mean_life_exp, group = 1), color = "red", size = 2) + labs(x = "Year", y = "Life expectancy") + theme_minimal()
Spatialize it
Overall, we can see a stable increase in life expectancy over the last 55 years. However, are there any differences between countries? What is the spatial distribution of the life expectancy? To answer that, we can download spatial data of the world using the rnaturalearth package:
world = ne_countries(returnclass = "sf") %>% select(iso_a2, name_long, continent)
Next, we need to combine the new spatial data with our non-spatial information of life expectancy.
First, the non-spatial data is reshaped into the wide form.
This way we are filling missing data with NA
instead of removing them
As a result, we will have the same number of countries (borders) for each year in our database.
Secondly, we are joining the spatial world
dataset with the non-spatial data_life_exp_wide
using the variable "iso_a2"
common to both datasets.
The last step is to convert the data back into a long form, where each pair of country and year corresponds to one row.
This also means that the spatial geometry for each country will be repeated for each time step.
data_life_exp_wide = data_life_exp %>% spread(year, life_exp) world_temporal = world %>% left_join(data_life_exp_wide, by = c("iso_a2")) %>% gather(year, life_exp, `1963`:`2013`)
Facet map
How to create a map showing temporal changes? One of the most straigforward ways is to use a facet plot:
my_map = tm_shape(world_temporal, projection = "robin") + tm_fill("life_exp", title = "Life expectancy", palette = "viridis") + tm_facets(by = "year", ncol = 3) my_map
Each map facet represents a different year. We can see that, on overall, the map colors shift from darker to more bright, indicating an increase in life expectancy. There is a noticeable spatial similarity (“spatial autocorrelation”) – European countries tend to have a longer life expectancy, while the lowest life expectancy is in Africa. This visualization also reveals (or just helps to see) a lot more, for example, life expectancy in China increased visibly faster than in neighboring countries or that there are missing values for Greenland before 1978.
There is, however, a downside of facet maps – each facet is relatively small and it is hard to see any details without zooming in. Alternatively, an animated map can be created, where each facet would be a next image frame.
Animated map
The code to create an animated map is almost identical to the facet map code.
There is only one important difference – the along
parameter should be used instead of by
:
my_ani = tm_shape(world_temporal, projection = "robin") + tm_fill("life_exp", title = "Life expectation", palette = "viridis") + tm_facets(along = "year")
The output, my_ani
, is a set of maps – one map per year.
It can be further converted into a proper animation with the tmap_animation()
function:
tmap_animation(my_ani, filename = "life_exp_animation.gif", width = 1500, height = 600, delay = 60)
The output presents the animated changes in life expectancy. The overall trend is still visible, but also small changes can be seen. It includes, for example, decreases in life expectancy in Cambodia in the 1970s and Rwanda in the 1990s.
Bonus
It is also possible to combine the two above methods – facet and animated map. Let’s try it on the data from South America:
world_temporal_sa = filter(world_temporal, continent == "South America") %>% na.omit()
To enable animated facet map, both arguments – by
and along
need to be set.
Here, countries will be presented on facets and each animation frame is a different year.
Feel free to test what would happen if you switch the arguments of by
and along
.
my_ani2 = tm_shape(world_temporal_sa) + tm_polygons("life_exp", title = "Life expectation", palette = "viridis") + tm_facets(by = "name_long", along = "year", nrow = 3) tmap_animation(my_ani2, filename = "life_exp_sa_animation.gif", width = 1600, height = 1000, delay = 60)
This way of presentation has a nice property – it allows for focus on values, instead of countries location or size. You can easily see values of the smallest countries and compare them to the largest ones.
I must admit that the bonus visualization example might not be the most appropriate. This visualization method is the best suited for comparing continuous features. For example, imagine animated facet maps comparing continuous surface phenomena (e.g. temperature or air quality) for each country through time. Try this method for yourself!
Final words
This blog post builds on the content in Chapter 8 of the book Geocomputation with R. To learn more about spatial data analysis, visualization and modeling using R visit the online version of the Geocomputation with R book at https://geocompr.robinlovelace.net/.
Acknowledgement
I’d like to thanks to Tal Galili (creator of http://www.r-bloggers.com/ and https://www.r-users.com/), and Maëlle Salmon, Bruce Zhao, Colin Fay, Eric Nantz, Hao Zhu, Jasmine Dumas, Jon Calder, Jonathan Carroll, Kun Ren, Tracy Shen, Wolfram Qin (team members of https://rweekly.org) for doing a great work of gathering and spreading blog posts, tutorials, and many other R-related resources. Keep your awesome work!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.