Since a few years, I’ve been fascinated by cartograms and tilemaps. I think they are an interesting option for visualizing spatial data at an aggregate (e.g. county, state, region) level. In this blog post, I will explain how you can create tilemaps in R.
I have already written several times about visualizations that depict inherently spatial data while foregoing spatial precision for a level of abstraction that helps – I would argue – information extraction. One such type of visualization are cartograms which I have covered, e.g., in this blog (in German) and in my private blog (in English) where I talk about hexagonal cartograms in general, show some examples I have built for the Oxford Internet Institute and The Guardian, and give a detailled methodology for generating such cartograms.
So far, in my cartograms, I have used hexagonal units and multiple such units per aggregate (region, state or country):
… to tilemaps
Now, if we do away with the idea that spatial units are generally made up of several atomic units (hexagons in the above example), we can abstract geography (spatial relationships and forms) even more. This process yields what is often called a tilemap. According to Wiktionary, a tilemap is a «two-dimensional grid made up of rectangular tiles of equal size, each of which can display an image.» The way most data viz practicioners use the term, they relax the requirement that tiles are to be rectangular (there are, e.g., hexagon- and triangle-based tilemaps). And the «images» mentioned in the definition can instead be data visualizations such as line graphs, bar graphs, pie charts, et cetera.
Over the last few months, I have been working on and off with tilemaps – often inspired by Corona. In what follows, I would like to specifically share an R-based workflow for generating such maps that I have used often.
Making tilemaps with R
In R, I usually use the «tidyverse» set of packages, i.e., ggplot2 for visualizations. For making and using tilemaps, I use geofacet, which can be thought of as a kind of a spatial sibling of
facet_grid() in ggplot2. The geofacet package has a nice introduction, a reference (obviously), and some examples on GitHub.
With geofacet, you can use existing tilemaps that are provided by the authors and users of the package. The introduction has a listing of available grids (about half-way down the page). You can easily see it in R as well:
# install.packages("geofacet") library(geofacet) get_grid_names()
However, even more grids may be available, as indicated in the printout. The full list of available grids can be gleaned from this JSON file.
geofacet comes with the example dataset
state_unemp. This represents «seasonally-adjusted December unemployment rate for each state (including DC) from 2000 to 2017». Using this, let’s look at a simple example:
This is produced by:
# Load necessary libraries library(ggplot2) library(geofacet) # Construct plot using <state_unemp> data ggplot(state_unemp, aes(year, rate)) + geom_line() + # Do the geo-facetting using the <state> attribute # in <state_unemp>. The contents of this needs to # match a key attribute in the grid you use. # geofacet will warn you about mis-matches. facet_geo(~ state, grid = "us_state_grid2") + xlab("Year") + ylab("Unemployment Rate (%)") + # Add some theme customization. This is merely to # ensure there is no overplotting of year labels. theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
If you are familiar with ggplot you can see that geofacet nicely ties into its usual functionality. But: I did have problems with labelling specific points in just one of the facetted plots (rather than all the «sub-plots»). By jumping through some hoops this can be achieved in ggplot2 with
facet_grid(), but I couldn’t get it to work with geofacet. Admittedly, this is a relatively rare use case, though.
You can also use geofacet for making browser-based dashboards with Shiny, as you can see in these examples.
Elevations in the US, Europe, and Switzerland
If you want to dive in a little deeper: I have compiled a GitHub repository with some code examples which you can use as building blocks for your own visualizations. For this, I have produced geofacetted slopegraphs of the minimum and maximum elevations of each state or country, in the US, in Europe, and in Switzerland (in an extended version: minimum, mean, and maximum elevations):
Minimum and maximum elevation
Extended versions including mean elevation for the US and Switzerland
All necessary data and code to produce these visualizations is in my GitHub repository.
Making your own grids
Most of my visualizations shown, or linked to, above are actually based on custom grids that I have created myself. To that end, geofacet offers a very nice browser-based visual editor for constructing grids. You simply start it in R using:
This opens the app in which you can specify entities as well as their position:
If you like, you can contribute your custom grid to the geofacet collection. This functionality is also part of the Geo Grid Designer. If you construct a custom grid using code in R and use it in a geofacet plot, the package will even ask you if you’d be willing to upload it as a user-contributed grid. If you prefer, you can start your foray into designing tilemap layouts with an existing grid and edit only some aspects of it. This can be done both in the Geo Grid Designer as well as using only code. The how-to is explained in the introduction to geofacet.
I hope I could demonstrate to you that tilemaps – when used in the right context – can be an interesting visualization option. And that they can be made quite easily in R, either by using a pre-made tilemap layout and applying your own data and visualization to it or by designing your very own tilemap layout and building from there. If you have questions about tilemaps, R, or about how to best leverage visualization techniques and tools in order to gain insights from your data, feel free to contact me.