4. Visualizing spatial data with the tmap package

Foreword on working directory, data and packages

The Data for this tutorial are provided via Github. In order to reproudce the code with your own data, replace the url with your local filepath

If you work locally, you may define the working directory

setwd("YOUR/FILEPATH") 
# this will not work. if you want to use it, define a path on your computer

This should be the place where your data and other folders are stored. more Information can be found here

Code chunks for saving data and results are disabeled in this tutorial (using a #). Please replace (“YOUR/FILEPATH”) with your own path.

The code is written in such a way, that packages will be automatically installed (if not already installed) and loaded. Packages will be stored in the default location of your computer.

Intro

The tmap package (short for thematic map) offers a wide variety of approaches to create thematic maps. The folowwing tutorial introduces static and dynamic maps created with the in-packaga data. It is inspired by the Introduction from the CRAN website.

Load the tmap package

if (!require(tmap)){install.packages("tmap"); library(tmap)}

We often use the tmap package for so-called “quick and dirty mapping” during data exploration.

Get tips and tricks. Random examples with in-package data

tmap_tip()
## Use size.max to set the value mapped to maximum symbol/bubble size. Use scale to increase (or decrease) all symbols/bubbles. 
## New since tmap 1.1 
## 
## data(metro)
## tm_shape(metro) + tm_bubbles("pop2020", size.max = 5e7, scale = 2) + tm_legend(outside = TRUE, outside.position = "bottom")
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()

Basic static Maps

Load data from tmap package.

data("World")

Check the structure and format of the data set

class(World)
## [1] "sf"         "data.frame"
str(World)
## Classes 'sf' and 'data.frame':   177 obs. of  16 variables:
##  $ iso_a3      : Factor w/ 177 levels "AFG","AGO","ALB",..: 1 2 3 4 5 6 7 8 9 10 ...
##  $ name        : Factor w/ 177 levels "Afghanistan",..: 1 4 2 166 6 7 5 56 8 9 ...
##  $ sovereignt  : Factor w/ 171 levels "Afghanistan",..: 1 4 2 159 6 7 5 52 8 9 ...
##  $ continent   : Factor w/ 8 levels "Africa","Antarctica",..: 3 1 4 3 8 3 2 7 6 4 ...
##  $ area        : Units: [km^2] num  652860 1246700 27400 71252 2736690 ...
##  $ pop_est     : num  28400000 12799293 3639453 4798491 40913584 ...
##  $ pop_est_dens: num  43.5 10.3 132.8 67.3 15 ...
##  $ economy     : Factor w/ 7 levels "1. Developed region: G7",..: 7 7 6 6 5 6 6 6 2 2 ...
##  $ income_grp  : Factor w/ 5 levels "1. High income: OECD",..: 5 3 4 2 3 4 2 2 1 1 ...
##  $ gdp_cap_est : num  784 8618 5993 38408 14027 ...
##  $ life_exp    : num  59.7 NA 77.3 NA 75.9 ...
##  $ well_being  : num  3.8 NA 5.5 NA 6.5 4.3 NA NA 7.2 7.4 ...
##  $ footprint   : num  0.79 NA 2.21 NA 3.14 2.23 NA NA 9.31 6.06 ...
##  $ inequality  : num  0.427 NA 0.165 NA 0.164 ...
##  $ HPI         : num  20.2 NA 36.8 NA 35.2 ...
##  $ geometry    :sfc_MULTIPOLYGON of length 177; first list element: List of 1
##   ..$ :List of 1
##   .. ..$ : num [1:69, 1:2] 61.2 62.2 63 63.2 64 ...
##   ..- attr(*, "class")= chr [1:3] "XY" "MULTIPOLYGON" "sfg"
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
##   ..- attr(*, "names")= chr [1:15] "iso_a3" "name" "sovereignt" "continent" ...
World
## Simple feature collection with 177 features and 15 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -180 ymin: -89.9 xmax: 180 ymax: 83.64513
## Geodetic CRS:  WGS 84
## First 10 features:
##    iso_a3                   name           sovereignt               continent
## 1     AFG            Afghanistan          Afghanistan                    Asia
## 2     AGO                 Angola               Angola                  Africa
## 3     ALB                Albania              Albania                  Europe
## 4     ARE   United Arab Emirates United Arab Emirates                    Asia
## 5     ARG              Argentina            Argentina           South America
## 6     ARM                Armenia              Armenia                    Asia
## 7     ATA             Antarctica           Antarctica              Antarctica
## 8     ATF Fr. S. Antarctic Lands               France Seven seas (open ocean)
## 9     AUS              Australia            Australia                 Oceania
## 10    AUT                Austria              Austria                  Europe
##                   area  pop_est pop_est_dens                    economy
## 1    652860.000 [km^2] 28400000 4.350090e+01  7. Least developed region
## 2   1246700.000 [km^2] 12799293 1.026654e+01  7. Least developed region
## 3     27400.000 [km^2]  3639453 1.328268e+02       6. Developing region
## 4     71252.172 [km^2]  4798491 6.734519e+01       6. Developing region
## 5   2736690.000 [km^2] 40913584 1.495003e+01    5. Emerging region: G20
## 6     28470.000 [km^2]  2967004 1.042151e+02       6. Developing region
## 7  12259213.973 [km^2]     3802 3.101341e-04       6. Developing region
## 8      7257.455 [km^2]      140 1.929051e-02       6. Developing region
## 9   7682300.000 [km^2] 21262641 2.767744e+00 2. Developed region: nonG7
## 10    82523.000 [km^2]  8210281 9.949082e+01 2. Developed region: nonG7
##                 income_grp gdp_cap_est life_exp well_being footprint inequality
## 1            5. Low income    784.1549   59.668        3.8      0.79 0.42655744
## 2   3. Upper middle income   8617.6635       NA         NA        NA         NA
## 3   4. Lower middle income   5992.6588   77.347        5.5      2.21 0.16513372
## 4  2. High income: nonOECD  38407.9078       NA         NA        NA         NA
## 5   3. Upper middle income  14027.1261   75.927        6.5      3.14 0.16423830
## 6   4. Lower middle income   6326.2469   74.446        4.3      2.23 0.21664810
## 7  2. High income: nonOECD 200000.0000       NA         NA        NA         NA
## 8  2. High income: nonOECD 114285.7143       NA         NA        NA         NA
## 9     1. High income: OECD  37634.0832   82.052        7.2      9.31 0.08067825
## 10    1. High income: OECD  40132.6093   81.004        7.4      6.06 0.07129351
##         HPI                       geometry
## 1  20.22535 MULTIPOLYGON (((61.21082 35...
## 2        NA MULTIPOLYGON (((16.32653 -5...
## 3  36.76687 MULTIPOLYGON (((20.59025 41...
## 4        NA MULTIPOLYGON (((51.57952 24...
## 5  35.19024 MULTIPOLYGON (((-65.5 -55.2...
## 6  25.66642 MULTIPOLYGON (((43.58275 41...
## 7        NA MULTIPOLYGON (((-59.57209 -...
## 8        NA MULTIPOLYGON (((68.935 -48....
## 9  21.22897 MULTIPOLYGON (((145.398 -40...
## 10 30.47822 MULTIPOLYGON (((16.97967 48...
names(World)
##  [1] "iso_a3"       "name"         "sovereignt"   "continent"    "area"        
##  [6] "pop_est"      "pop_est_dens" "economy"      "income_grp"   "gdp_cap_est" 
## [11] "life_exp"     "well_being"   "footprint"    "inequality"   "HPI"         
## [16] "geometry"

Summarize data

summary(World)
##      iso_a3             name                        sovereignt 
##  AFG    :  1   Afghanistan:  1   France                  :  3  
##  AGO    :  1   Albania    :  1   Denmark                 :  2  
##  ALB    :  1   Algeria    :  1   Israel                  :  2  
##  ARE    :  1   Angola     :  1   United Kingdom          :  2  
##  ARG    :  1   Antarctica :  1   United States of America:  2  
##  ARM    :  1   Argentina  :  1   Afghanistan             :  1  
##  (Other):171   (Other)    :171   (Other)                 :165  
##          continent       area             pop_est           pop_est_dens      
##  Africa       :51   Min.   :    2590   Min.   :1.400e+02   Min.   :   0.0003  
##  Asia         :47   1st Qu.:   42390   1st Qu.:3.442e+06   1st Qu.:  20.8203  
##  Europe       :39   Median :  183630   Median :9.036e+06   Median :  65.3438  
##  North America:18   Mean   :  814568   Mean   :3.827e+07   Mean   : 105.5498  
##  South America:13   3rd Qu.:  622980   3rd Qu.:2.595e+07   3rd Qu.: 116.8924  
##  Oceania      : 7   Max.   :16376870   Max.   :1.339e+09   Max.   :1198.8237  
##  (Other)      : 2                                                             
##                        economy                     income_grp
##  1. Developed region: G7   : 7   1. High income: OECD   :32  
##  2. Developed region: nonG7:32   2. High income: nonOECD:17  
##  3. Emerging region: BRIC  : 4   3. Upper middle income :44  
##  4. Emerging region: MIKT  : 4   4. Lower middle income :47  
##  5. Emerging region: G20   :19   5. Low income          :37  
##  6. Developing region      :66                               
##  7. Least developed region :45                               
##   gdp_cap_est          life_exp       well_being      footprint     
##  Min.   :   300.5   Min.   :48.91   Min.   :2.867   Min.   : 0.610  
##  1st Qu.:  2215.4   1st Qu.:65.04   1st Qu.:4.575   1st Qu.: 1.425  
##  Median :  7394.8   Median :73.24   Median :5.200   Median : 2.604  
##  Mean   : 14977.1   Mean   :70.80   Mean   :5.412   Mean   : 3.223  
##  3rd Qu.: 19193.8   3rd Qu.:76.93   3rd Qu.:6.300   3rd Qu.: 4.482  
##  Max.   :200000.0   Max.   :83.24   Max.   :7.800   Max.   :15.820  
##  NA's   :1          NA's   :41      NA's   :41      NA's   :41      
##    inequality           HPI                 geometry  
##  Min.   :0.04322   Min.   :12.78   MULTIPOLYGON :177  
##  1st Qu.:0.13931   1st Qu.:21.21   epsg:4326    :  0  
##  Median :0.21293   Median :26.29   +proj=long...:  0  
##  Mean   :0.23427   Mean   :26.48                      
##  3rd Qu.:0.32932   3rd Qu.:31.73                      
##  Max.   :0.50734   Max.   :44.71                      
##  NA's   :41        NA's   :41

Plot population estimate and check histogram and summarize to get an overview of the data.

plot(World$pop_est)

hist(World$pop_est)

summary(World$pop_est)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 1.400e+02 3.442e+06 9.036e+06 3.827e+07 2.595e+07 1.339e+09

Plot a simple Map of HPI (Happy Planet Index)

tm_shape(World) +
  tm_polygons("HPI")

Plot a simple Map of life expectancy

tm_shape(World) +
  tm_polygons("life_exp")

Interactive Maps

The mode of plotting can be set with the function tmap_mode –> static image “plot” mode

tmap_mode("plot")
## tmap mode set to plotting
tm_shape(World) +
  tm_polygons("life_exp")

Or viewed interactively using “view” modes –> uses leaflet TO DO

tmap_mode("view")
tm_shape(World) +
  tm_polygons("life_exp")
# l <- tmap_mode("view") +
#   tm_shape(World) +
#   tm_polygons("life_exp")
# frameWidget(l)

Plot Multiple shapes and layers

We now combine several layers which are included in the tmap package:

  • ‘metro’ population times series from 1950 to 2030. All metro areas >1 mio inhabitants
  • ‘Land’ Spatial data of global land cover
  • ‘rivers’ major rivers worldwide

We now want to plot them all together

data(World, metro, rivers, land)

tmap_mode("plot")
## tmap mode set to plotting
## tmap mode set to plotting

tm_shape(land) +
  tm_raster("elevation", palette = terrain.colors(10)) +
  tm_shape(World) +
  tm_borders("white", lwd = .5)+
  tm_text("iso_a3", size = "AREA")+
  tm_shape(metro) + 
  tm_symbols(col = "red", size = "pop2020", scale = .5) +
  tm_legend(show = FALSE)
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()

Facets - multiple plots in one window

There are multiple ways to do so:

By assigning multiple variable names to one aesthetic:

In this example we display “HPI” and “Economy” of the data set together and interactively (interactivity is turned off on the website due to package restrictions. It should work on your computer though).

tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(World) +
  tm_polygons(c("HPI", "economy")) +
  tm_facets(sync = TRUE, ncol = 2)

By splitting the spatial data with the by argument of tm_facets

In this example we calculate the percentage of the male population in the prvinces of the Netherlands. The data are provided by the tmap package.

tmap_mode("plot")
## tmap mode set to plotting
## tmap mode set to plotting
data(NLD_muni) 

NLD_muni$perc_men <- NLD_muni$pop_men / NLD_muni$population * 100

tm_shape(NLD_muni) +
  tm_polygons("perc_men", palette = "RdYlBu") +
  tm_facets(by = "province")
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()

By using the tmap_arrange function

In this example we calculate the population density of the communities of the Netherlands, simply by using the convert2density argument in the tm_polygons function. In it the area size is either approximated from the shape object, or given by the argument area. Also, we use the tm_bubbles function to create proportionate bubbles.

tmap_mode("plot")
## tmap mode set to plotting
## tmap mode set to plotting

data(NLD_muni)
tm1 <- tm_shape(NLD_muni) + tm_polygons("population", convert2density = TRUE)
tm2 <- tm_shape(NLD_muni) + tm_bubbles(size = "population")

tmap_arrange(tm1, tm2)
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## Legend labels were too wide. Therefore, legend.text.size has been set to 0.32. Increase legend.width (argument of tm_layout) to make the legend wider and therefore the labels larger.

Basemaps and overlay tile maps

Tiled basemaps can be added with the layer function tm_basemap. Semi-transparent overlay maps (for example annotation labels) can be added with tm_tiles.

tmap_mode("plot")
## tmap mode set to plotting
tm_basemap("Stamen.Watercolor") +
  tm_shape(metro) + tm_bubbles(size = "pop2020", col = "red") +
  tm_tiles("Stamen.TonerLabels")
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()

To see all available basemaps for tm_tiles check link http://leaflet-extras.github.io/leaflet-providers/preview/ for example basemaps from ESRI

tm_basemap("Esri.WorldImagery") +
  tm_shape(metro) + tm_bubbles(size = "pop2020", col = "red") +
  tm_tiles("Stamen.TonerLabels")
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()
## old-style crs object detected; please recreate object with a recent sf::st_crs()

#O ptions and style with tm_layout

tmap_mode("plot")
## tmap mode set to plotting
## tmap mode set to plotting
tm_shape(World) +
  tm_polygons("HPI") +
  tm_layout(bg.color = "skyblue", inner.margins = c(0, .02, .02, .02))

tmap_options(bg.color = "black", legend.text.color = "white")
tm_shape(World) +
  tm_polygons("HPI", legend.title = "Happy Planet Index")

tmap_style("natural")
## tmap style set to "natural"
## other available styles are: "white", "gray", "cobalt", "col_blind", "albatross", "beaver", "bw", "classic", "watercolor"
tm_shape(World) +
  tm_polygons("HPI", legend.title = "Happy Planet Index")

See what options have been changed

tmap_options_diff()
## current tmap options (style "natural") that are different from default tmap options (style "white"):
## $bg.color
## [1] "lightskyblue1"
## 
## $aes.color
##              fill           borders           symbols              dots 
## "darkolivegreen3"           "black"         "tomato2"       "firebrick" 
##             lines              text                na              null 
##       "steelblue"           "black"           "white"          "grey70" 
## 
## $aes.palette
## $aes.palette$seq
## [1] "YlGn"
## 
## $aes.palette$div
## [1] "RdYlGn"
## 
## $aes.palette$cat
## [1] "Set3"
## 
## 
## $earth.boundary
## [1] TRUE
## 
## $space.color
## [1] "white"
## 
## $legend.frame
## [1] TRUE
## 
## $legend.bg.color
## [1] "grey90"
## 
## $basemaps
## [1] "Esri.NatGeoWorldMap"
## 
## $basemaps.alpha
## [1] 1

Reset the options to the default values

tmap_options_reset()
## tmap options successfully reset

Exporting maps

tm <- tm_shape(World) +
  tm_polygons("HPI", legend.title = "Happy Planet Index")

save an image (“plot” mode) to the working directory.

tmap_save(tm, filename = "world_map.png")

save as stand-alone HTML file (“view” mode)

tmap_save(tm, filename = "world_map.html")

Quick and dirty mapping

Use the qtm function if you want a simply map fast

qtm(World, fill = "HPI", fill.pallete = "RdYlGn")

Previous
Next