tmap in a nutshell

With the tmap package, thematic maps can be generated with great flexibility. The syntax for creating plots is similar to that of ggplot2. Also, the standard work flow that is needed to create a thematic map is embedded in tmap; convenient functions for reading and writing ESRI shape files, setting the proper projection, and appending data are contained in the tmap package.

Shape objects

We refer to shape objects as objects from the class Spatial or Raster, respectively from the sp and the raster package. The six supported subclasses are:

Without data With data
Polygons SpatialPolygons SpatialPolygonsDataFrame
Points SpatialPoints SpatialPointsDataFrame
Lines SpatialLines SpatialLinesDataFrame
Raster SpatialGrid SpatialGridDataFrame
Raster SpatialPixels SpatialPixelsDataFrame
Raster RasterLayer
Raster RasterBrick
Raster RasterStack

Obviously, shape objects with data (the right-hand side column) are recommended, since data is what we want to show.

Load shape object of Europe (contained in this package):


Shape objects in ESRI format can be read with read_shape and written with write_shape. Projection can be get and set with get_projection and set_projection respectively. Note: projections can also directly (and temporarily) be set in the plotting method (as argument of tm_shape, see below).

Quick thematic map

The plotting syntax is based on that of ggplot. The qtm function is tmap's equivalent to ggplot2's qplot. The first, and only required argument is a shape object:


plot of chunk unnamed-chunk-2

So, by default, the polygons (in case the shape object is a SpatialPolygonsDataFrame) are filled with light grey, and the polygon borders are drawn in dark grey.

A choropleth is created with the following code:

qtm(Europe, fill="gdp_cap_est", text="iso_a3", text.size="AREA", root=5, fill.title="GDP per capita", 
    fill.textNA="Non-European countries", theme="Europe")

plot of chunk unnamed-chunk-3

In this code, fill and text serve as aesthetics. Both gdp_cap_est and iso_a3 are variables of the data contained in the shape object Europe. A color palette, in this case the qualitative palette from yellow to green, is mapped to the values of gdp_cap_est. The variable iso_a3 contains the text labels, in this case the country codes. The arguments text.size and root determine the fontsizes of the text labels (in this case, the fifth root of the area sizes are taken). The fill.title argument is the title for the fill-legend. The argument fill.textNA is the legend text for missing values. The theme argument specifies predefined layout settings for this shape object.

The function qtm offers the same flexibility as the main plotting method (to be described next). However, for more complex plots, the main plotting method is recommended for tis readability.

Plotting with tmap elements

The main plotting method, the equivalent to ggplot2's ggplot, consists of elements that start with tm_. The first element to start with is tm_shape, which specifies the shape object. Next, one, or a combination of the following drawing layers should be specified:

Drawing layer Description Main arguments
tm_fill Fills the polygons col*
tm_borders Draws polygon borders col, lwd
tm_bubbles Draws bubbles size*, col*
tm_lines Draws polylines col*, lwd*
tm_lines Draws a raster col*
tm_text Add text labels text+, size+
tm_grid Add coordinate grid lines
tm_credits Add credits text label
tm_scale_bar Add scale bar

The arguments with superscript symbols can be used as aesthetics. Both constant values as well as data variable names can be assigned to these arguments. For instance, tm_fill(col="blue") colors all polygons blue, while tm_fill(col="var1"), where "var1" is the name of a data variable in the shape object, creates a choropleth. Only for the five arguments with a *, a legend is created (and by default shown).

The last plot is reproduced as follows:

tm_shape(Europe) +
    tm_fill("gdp_cap_est", textNA="Non-European countries", title="GDP per capita") +
    tm_borders() +
    tm_text("iso_a3", size="AREA", root=5) + 

We refer to tm_shape and its subsequent drawing layers (all of the elements in the last example except tm_layout) as a group. Multiple groups can be stacked. To illustrate this, let's create a complex map of Europe:


tm_shape(Europe) +
    tm_fill("pop_est_dens", style="kmeans", textNA="Non-European countries", 
    title="Country population density (per km2)") +
    tm_borders() +
tm_shape(rivers) +
    tm_lines("dodgerblue3") +
tm_shape(metro) +
    tm_text("name", size="pop2010", scale=1, ymod=-.02, root=4, size.lowerbound = .60, 
        bg.color="yellow", bg.alpha = .5) + 
    tm_bubbles("pop2010", "red", border.col = "black", border.lwd=1, size.lim = c(0, 11e6), 
        sizes.legend = seq(2e6,10e6, by=2e6), title.size="Metropolitan Population") +
tm_shape(Europe) +
    tm_text("iso_a3", size="area", scale=1.5, root=8, size.lowerbound = .40, 
        fontface="bold", case=NA, fontcolor = "gray35") + 
tm_layout_Europe("Map of Europe")

plot of chunk unnamed-chunk-5

Thinks to learn from this code:

Small multiples

Small multiples are generated in two ways:

  1. By assigning multiple values to at least one of the 5 aesthetic arguments (in the table above indicated by the * symbol)
tm_shape(Europe) +
    tm_fill(c("pop_est_dens", "gdp_cap_est"), style="kmeans", 
        title=c("Population density", "GDP per capita")) +

plot of chunk unnamed-chunk-6

  1. By defining a group-by variable in tm_facets:
tm_shape(Europe) +
    tm_fill("gdp_cap_est", style="kmeans", title="GDP per capita") +
    tm_facets("part") +

plot of chunk unnamed-chunk-7

The scales of each aesthetic argument can be set to either fixed or free, and also, the coordinate ranges of the small multiples:

tm_shape(Europe[Europe$continent=="Europe",]) +
    tm_fill("part", thres.poly = 0) +
    tm_facets("name", free.coords=TRUE, drop.shapes=TRUE) +
tm_layout( = FALSE, title.position = c("center", "center"), title.size = 2)

plot of chunk unnamed-chunk-8

Remarks: the argument drop.shapes is used to drop all non-selected shapes. If drop.shapes=FALSE then neighboring countries are also visible. The argument thres.poly is set to 0 in order to calculate the aesthetics for all polygons, so also for very small ones, like Vatican.


The layout of the thematic map can be changed with tm_layout, for instance regarding the legend:

pal8 <- c("#33A02C", "#B2DF8A", "#FDBF6F", "#1F78B4", "#999999", "#E31A1C", "#E6E6E6", "#A6CEE3")
tm_shape(land, ylim = c(-88,88), relative=FALSE) +
    tm_raster("cover_cls", palette = pal8, title="Global Land Cover", legend.hist=TRUE, legend.hist.z=0) +
tm_shape(World) +
    tm_borders() +
    legend.position = c("left","bottom"), = "white",, 
    legend.width=.2, legend.height=.6, 

plot of chunk unnamed-chunk-9

Also, the outer and inner margins as well as the aspect ratio are determined with tm_layout:

(tm <- tm_shape(World) +
    tm_fill() +
    tm_borders() +
tm_layout(bg.color = "lightblue", outer.margins=c(.05,0,.05,0), 
    inner.margins=c(0,0,.02,0), asp=0))

plot of chunk unnamed-chunk-10

The behaviour of outer.margins, inner.margins, and asp are correlated. To see the viewports that these arguments determine, the design mode can be enabled:

tm + tm_layout(design.mode=TRUE)

plot of chunk unnamed-chunk-11

## aspect ratio device (yellow): 1.428571 
## aspect ratio frame (blue): 1.587302 
## aspect ratio master shape, World (red): 1.979637

The red rectangle is the bounding box of the shape object. Both inner.margins and asp determine the measurements of the frame, indicated by the blue rectagle. Setting the left inner margin is useful to have extra space for the legend. Setting the aspect ratio is handy when the plot is saved to an image with a specific resolution. For instance, to save a thematic World map as a png image of 1920 by 1080 pixels, the setting outer.margins=0, asp=1920/1080 is recommended. When asp=0, as in the example above, the aspect ratio of the device (given the outer margins) is taken.

Complete work flow for creating thematic maps

Besides the ggplot2-style plotting functions, the package also offers functions to set up a work flow that is sufficient for most statistical applications.

Tips n' tricks

  1. Selections can be made by treating the data.frame of the shape object:
tm_shape(Europe[Europe$name=="Austria", ]) +

plot of chunk unnamed-chunk-14

  1. A one-item legend can be generated by using a categorical data variable with a one category, and assigning a single color value to palette:

rivers$constant <- factor("Rivers")
tm_shape(World) +
    tm_fill() +
tm_shape(rivers) +
    tm_lines(col="constant", palette="dodgerblue3", title.col="World map") +

plot of chunk unnamed-chunk-15

  1. Each drawing element has a scalar arguemnt called scale. The overall scaling and font sizes can be set by the scale argument in tm_layout.

  2. When the element tm_grid is added to the plot, grid lines are plotted.