Producing an inset map with the tmap package in R
Asked Answered
A

2

8

I am trying to produce an inset map of London alongside a larger map of the UK. I'm using the package "tmap" which I have found to be an excellent package and particularly easy to move to having used ggplot2 for a while. However, the documentation on how to produce an inset map using tmap is a bit unclear. The reference manual describes how it should be possible to produce an inset map using:

    save_tm(...insets_tm = NULL, insets_vp = NULL) 

but it is not clear how the second command, insets_vp, should be used. I have only found one example which actually provides suggested syntax for producing an insetmap using tmap:

    alaska <- tm_shape(shp_alaska) + … print(alaska, vp=viewport(x=.1, 
    y=.15, width=.2, height=.3)) 

See here for the source of the above code. This doesn't actually show how the map of the USA and Alaska/Hawaii are combined. As for my own attempts at coding, I have tried the following (dplyr, magrittr, rgdal, GISTools, RColorBrewer, tmap are all loaded, R vn 3.3.2, RStudio 1.0.136):

  1. I first create two tmap objects polygon and points for all of the UK (UK_Im_Sec) and London (London_Im_Sec):

    UK_Im_Sec<-tm_shape(UKNI_LA_ll, is.master = TRUE)+
    tm_borders(lwd=0.25)+
    tm_shape(Immobile_residuals)+
    tm_dots(col="Sec_Name", style="cat", palette="Set1", title="Socio-economic background (NS-SEC)")+
    tm_layout(title="Mapping outlier residuals - non-predicted 'immobility' (Social class)", title.size = 3.0,
        title.position=c("center","TOP"),legend.outside = TRUE,
        legend.outside.position = "right",frame = FALSE)
    
    LDN_Im_Sec<-tm_shape(Immobile_resids_LDN)+
    tm_dots(col="Sec_Name", style="cat", palette="Set1", size = 0.25,title="Socio-economic background (NS-SEC)")+
    tm_shape(LDN_Poly, is.master = TRUE)+
    tm_borders(lwd=0.25)+
    tm_text(text="NAME", size = 0.6, auto.placement=TRUE)+
    tm_layout("London",title.position = c("center", "BOTTOM"),legend.outside = TRUE, legend.outside.position = "right", frame =  FALSE)
    
  2. I then try to save out a pdf which combines both objects:

    save_tmap(UK_Im_Sec,insets_tm = LDN_Im_Sec,filename="ZRMdlNoRg_SEC_-3to-5SDs_ImmobResids_FINAL.pdf", dpi=600)
    

This prints the pdf but only with the map of the UK. So,

  1. I try and add insets_vp into the code:

    save_tmap(UK_Im_Sec,insets_tm = LDN_Im_Sec,insets_vp=UK_Im_Sec, filename="ZRMdlNoRg_SEC_-3to-5SDs_ImmobResids_FINAL.pdf", dpi=600)
    

But this gives the following error code:

    Error in save_tmap(UK_Im_Sec, insets_tm = LDN_Im_Sec, insets_vp = UK_Im_Sec,  : 
    Insets and/or its viewports not in the correct format
  1. I then try to combine the suggested syntax for print(x, viewport=(x=,y=,h=,w=) with insets_vp, as follows:

    save_tmap(UK_Im_Sec,insets_tm = LDN_Im_Sec,insets_vp=viewport(x=2, y=.15, width=.2, height=.3), filename="ZRMdlNoRg_SEC_-3to-5SDs_ImmobResids_FINAL.pdf", dpi=600)
    Error in inherits(insets_vp, "viewport") : 
    could not find function "viewport"
    

I know that other people have had difficulty producing inset maps in other packages and that there are questions that have already been asked and resolved for other packages, notably in ggplot (I can't link to the questions because of limits on links), but as far as I know there is nothing on this particular tmap issue.

This is my first question here so apologies for any errors in laying out the question.

Acred answered 7/2, 2017 at 9:50 Comment(0)
S
5

You'll need to load the grid package. So, this should work

library(grid)
save_tmap(UK_Im_Sec,insets_tm = LDN_Im_Sec,insets_vp=viewport(x=2, y=.15, width=.2, height=.3), filename="ZRMdlNoRg_SEC_-3to-5SDs_ImmobResids_FINAL.pdf", dpi=600)

I'll update the US choropleth demo soon, with a save_tmap example.

Sphenic answered 7/2, 2017 at 10:58 Comment(6)
Well there you go @SJPG, from the horse's mouth (figuratively at least)Berserk
Hi thanks very much for getting back to me so quickly, I tried this but received the following error when trying to install grid Warning in install.packages : package ‘grid’ is not available (for R version 3.3.2) Warning in install.packages : package ‘grid’ is a base package, and should not be updatedAcred
I suspect the problem does probably lie with the version of R I am using, especially as the latest (and very recently updated version of grid) was built for a newer version of R. [stat.ethz.ch/R-manual/R-devel/library/grid/DESCRIPTION] This is the problem of working on a computer where you have to ask for IT to update software! Will let you know if this resolves the problemAcred
It could also be to do with grid having been included in base R? [link] (https://mcmap.net/q/640544/-r-package-grid-disappeared)Acred
In case anyone is still following this, grid now works - I think one of the packages listed above was shielding viewport from working somehow. The save_tmap code runs smoothly when only tmap is loaded but the inset still doesn't actually show up on the pdf. I have tried various x/y/w/h permutations but they don't seem to make any difference...Acred
Following this thread a year later, I am correct in understanding that the demo has been updated (clarifying any confusing from feb 2017) and that the person who wrote the other answer to this question just used that demo for their answer? Regardless, the demo is very clear, while this answer is sparse. Perhaps add the link directly to the answer?Arabia
B
3

The last chart in the tmap demo documentation has insets of Alaska and Hawaii. Below is the code, I've just removed the fill variable:

library("readxl")
library("maptools")
library("grid")
library("tmap")
library("tmaptools")

# function to obtain US county shape
get_US_county_2010_shape <- function() {
  dir <- tempdir()
  download.file("http://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_050_00_20m.zip", destfile = file.path(dir, "gz_2010_us_050_00_20m.zip"))
  unzip(file.path(dir, "gz_2010_us_050_00_20m.zip"), exdir = dir)
  read_shape(file.path(dir, "gz_2010_us_050_00_20m.shp"))
}

# obtain US county shape
US <- get_US_county_2010_shape()

# split shape 
US_cont <- US[!(US$STATE %in% c("02","15","72")),]  
US_AK <- US[US$STATE == "02", ]
US_HI <- US[US$STATE == "15",]

# create state boundaries
US_states <- unionSpatialPolygons(US_cont, IDs=US_cont$STATE)

After setting up the shapefiles, here is where the viewport windows are added to the plot:

# change back to the plotting mode
tmap_mode("plot")

# plot contiguous US
tm_shape(US_cont, projection=2163) +
  tm_polygons(border.col = "grey50", border.alpha = .5, title = "", showNA = TRUE) +
  tm_shape(US_states) +
  tm_borders(lwd=1, col = "black", alpha = .5) +
  tm_credits("Data @ Unites States Department of Agriculture\nShape @ Unites States Census Bureau", position = c("right", "bottom")) +
  tm_layout(title.position = c("center", "top"), 
            legend.position = c("right", "bottom"), 
            frame = FALSE, 
            inner.margins = c(0.1, 0.1, 0.05, 0.05))

# Alaska inset
m_AK <- tm_shape(US_AK, projection = 3338) +
  tm_polygons(border.col = "grey50", border.alpha = .5, breaks = seq(10, 50, by = 5)) +
  tm_layout("Alaska", legend.show = FALSE, bg.color = NA, title.size = 0.8, frame = FALSE)

# Hawaii inset
m_HI <- tm_shape(US_HI, projection = 3759) +
  tm_polygons(border.col = "grey50", border.alpha = .5, breaks=seq(10, 50, by = 5)) +
  tm_layout(legend.show = FALSE, bg.color=NA, title.position = c("LEFT", "BOTTOM"), title.size = 0.8, frame=FALSE)

# print insets
print(m_AK, vp=viewport(x= 0.15, y= 0.15, width= 0.3, height= 0.3))
print(m_HI, vp=viewport(x= 0.4, y= 0.1, width= 0.2, height= 0.1))

Source: I've adapted this from https://github.com/mtennekes/tmap/tree/master/demo/USChoropleth

Berserk answered 7/2, 2017 at 10:37 Comment(1)
Thanks very much for this! I will have a go at working through this later this afternoon, and let you know how I get on. Sorry I didn't check the github page you linked to, didn't think to look there!Acred

© 2022 - 2024 — McMap. All rights reserved.