Search code examples
rr-markdowntmap

tmap_arrange output quality in R markdown


Is there any way to control the output resolution when using tmap_arrange?

Example using the shape files of Dutch regions from the cbs api and assigning population data (random for simplicity). Each map on it's own is good quality. However, if I use tmap_arrange it is much lower resolution and am struggling to find a way to improve it.

If I tmap_save as pngs I can specify the resolution and reimport that improves matters, but it adds a lot of steps.

Example is an R markdown script.


title: "tmaps of Netherlands regions" date: "r Sys.Date()" output: html_document

knitr::opts_chunk$set(warning = FALSE, message = FALSE, error=FALSE) 

library(knitr)
library(markdown)
library(cbsodataR)
library(tidyverse)
library(httr)
library(sf)
library(tmap)

## download geometry

list_of_geos <- c("landsdeel", "provincie", "coropgebied", "gemeente")

## loop through main geometries

for (geo_nam in list_of_geos){

## define url
url <- parse_url("https://service.pdok.nl/cbs/gebiedsindelingen/2023/wfs/v1_0")
## build request
url$query <- list(service = "WFS",
                  version = "2.0.0",
                  request = "GetFeature",
                  typename = paste0("gebiedsindelingen:", geo_nam,  "_gegeneraliseerd"),
                  outputFormat = "application/json")
request <- build_url(url)
## request shapes
geo_sf <- st_read(request, quiet = TRUE)
## assign environment name
assign(geo_nam, geo_sf)

}

## define a palette
me_pal <- c("#0000b3", "#0000eb", "#1d00ff", "#4a00ff", "#7600ff", "#a211ee", "#cf2ed1", "#fb4ab5", 
          "#ff6798", "#ff837c", "#ff9f60", "#ffbc43", "#ffd827", "#fff50a")

## make up population data
landsdeel$population <- as.numeric(sample(1000000:9000000, size = nrow(landsdeel)))

## define breaks
bks <- seq(1000000,9000000, length.out = 25)

## generate tmap
tm1 <- tm_shape(landsdeel) +
tm_polygons('population', palette = me_pal, border.col = 'black', breaks = bks, title = "Population Landsdeel")+
tm_layout(legend.outside = TRUE, frame = FALSE, legend.width = 2)+
tm_text("statnaam", size = 1/4) + tm_layout(frame = FALSE)

tm1

coropgebied$population <- as.numeric(sample(0:1000000, size = nrow(coropgebied)))

bks <- seq(0,1000000, length.out = 25)

tm2 <- tm_shape(coropgebied) +
tm_polygons('population', palette = me_pal, border.col = 'black', breaks = bks, title = "Population Coropgebied")+
tm_layout(legend.outside = TRUE, frame = FALSE, legend.width = 2)

tm2

provincie$population <- as.numeric(sample(100000:4000000, size = nrow(provincie)))

bks <- seq(100000,4000000, length.out = 25)

tm3 <- tm_shape(provincie) +
tm_polygons('population', palette = me_pal, border.col = 'black', breaks = bks, title = "Population Provincie")+
tm_layout(legend.outside = TRUE, frame = FALSE, legend.width = 2)+
tm_text("statnaam", size = 1/4) + tm_layout(frame = FALSE)

tm3

gemeente$population <- as.numeric(sample(0:900000, size = nrow(gemeente)))

bks <- seq(0,900000, length.out = 25)

tm4 <- tm_shape(gemeente) +
tm_polygons('population', palette = me_pal, border.col = 'black', breaks = bks, title = "Population Gemeente")+
tm_layout(legend.outside = TRUE, frame = FALSE, legend.width = 2)

tm4

## arrange 2 by 2
tmap_arrange(tm1, tm2, tm3, tm4, ncol = 2, nrow = 2)


Solution

  • Simply put your arranged maps into a new variable and save it via tmap_save:

    tm_all <- tmap_arrange(tm1, tm2, tm3, tm4, ncol = 2, nrow = 2)
    tmap_save(tm_all, "test_map.png", dpi = 600)
    

    or directly:

    tmap_arrange(tm1, tm2, tm3, tm4, ncol = 2, nrow = 2) %>% tmap_save("test_map.png", dpi = 600)
    

    Resolution is set via dpi.

    In your markdown document you can also adjust the resolution of the corresponding chunk e.g. via {r setup, include=FALSE, dpi = 600}.