Creating continuous coloured maps with osmplotr

reproducible research
maps
Author

Thierry Onkelinx

Published

July 17, 2017

During useR!2017 I attended a talk by Mark Padgham titled Maps are data, so why no plot data on a map. In this blog post I will recreate the map from an earlier blog post on estimating densities from a point pattern.

Let’s start by loading all required packages.

library(dplyr)
library(leaflet)
library(MASS)
library(osmplotr)
library(sf)
library(wk)

I rearranged the code from the previous blog post in two chunks. The first chunk calculate the density and is required for both the leaflet and the osmplotr solution. See the earlier blog post for the details on what the code does.

crs_wgs84 <- st_crs(4326)
crs_lambert <- st_crs(31370)
read.delim("../statistics/data/points.txt", sep = " ") |>
  st_as_sf(coords = c("lon", "lat"), crs = crs_wgs84) |>
  st_transform(crs = crs_lambert) -> points
st_bbox(points) |>
  matrix(nrow = 2) -> bb
bb <- bb / params$cellsize
bb[, 1] <- floor(bb[, 1]) * params$cellsize
bb[, 2] <- ceiling(bb[, 2]) * params$cellsize
apply(bb, 1, diff) -> ranges
coords <- st_coordinates(points)
coords[, "X"] |>
  kde2d(
    y = coords[, "Y"], n = (rev(ranges) / params$cellsize) + 1,
    lims = as.vector(t(bb))
  ) -> dens

The second chunk converts the density to a simple features object so we can plot it with leaflet.

expand.grid(lon = dens$x, lat = dens$y) |>
  st_as_sf(coords = c("lon", "lat"), crs = crs_lambert) |>
  st_make_grid(
    cellsize = params$cellsize, offset = bb[, 1] - 0.5 * params$cellsize
  ) |>
  st_as_sf() |>
  mutate(
    density = as.vector(t(dens$z)) * params$cellsize ^ 2
  ) |>
  wk_transform(
    wk_affine_scale(params$scale, params$scale)
  ) |>
  wk_transform(
    wk_affine_translate(-bb[1, 1], -bb[2, 1])
  ) |>
  st_set_crs(crs_lambert) |>
  st_transform(crs = crs_wgs84) -> dens_wgs84

The next chunk gets the OpenStreetMap background and overlays is with the density map (Figure 1). The density layer needs to be somewhat transparent in order to see the background image.

pal <- colorNumeric(
  palette = rev(rainbow(100, start = 0, end = 0.7)),
  domain = c(0, dens_wgs84$density)
)
leaflet(dens_wgs84) |>
  addTiles() |>
  addPolygons(color = ~pal(density), stroke = FALSE, fillOpacity = 0.5) |>
  addLegend(pal = pal, values = ~density)
Figure 1: Estimated density (number of points per grid cell)

The osmplotr package uses a set of points to create the colours. x and y hold the longitude an latitude, z the variable for the colour value.

expand.grid(lon = dens$x, lat = dens$y) |>
  mutate(z = as.vector(dens$z) * params$cellsize ^ 2) |>
  st_as_sf(coords = c("lon", "lat"), crs = crs_lambert) |>
  wk_transform(
    wk_affine_scale(params$scale, params$scale)
  ) |>
  wk_transform(
    wk_affine_translate(-bb[1, 1], -bb[2, 1])
  ) |>
  st_set_crs(crs_lambert) |>
  st_transform(crs = crs_wgs84) %>%
  bind_cols(st_coordinates(.)) |>
  st_drop_geometry() |>
  dplyr::select(x = "X", y = "Y", "z") -> dataset

The next step is to download the required OpenStreetMap (OSM) data. Here I selected all roads and paths (“highway” in OSM terminology) and all the buildings.

bb_osm <- st_bbox(dens_wgs84)
roads <- extract_osm_objects(key = "highway", bbox = bb_osm)
buildings <- extract_osm_objects(key = "building", bbox = bb_osm)
osm_basemap(bbox = matrix(bb_osm, ncol = 2), bg = "gray95") |>
  add_osm_surface(
    buildings, dat = dataset, cols = rainbow(100, end = 0.7), bg = "gray85"
  ) |>
  add_osm_surface(
    roads, dat = dataset, bg = "gray85",
    cols = rainbow(100, end = 0.7) |>
      adjust_colours(-0.2)
  ) |>
  add_colourbar(
    cols = rainbow(100, end = 0.7), zlims = range(dataset$z)
  ) |>
  add_axes()

osmplotr image of density

Pro and contra of osmplotr for continuous coloured maps

Note that osmplotr can create maps with discrete colours too. This was outside the scope of this blog post. See the osmplotr vignettes on plotting basic maps and data maps (both categorical and continuous).

Much depends on the kind of data you want to display and the required accuracy. osmplotr uses the objects from OSM. Each OSM feature will get a uniform colour depending on the location of the centroid. Unless you data matched with the OSM data, it is not possible to use the accurate location of the data points.

Another point is scale and resolution of the OSM data. In case of an urban area were all individual buildings are available and the size of the individual buildings is small compared to the size of the map, then the osmplotr map works quite well.

Session info

These R packages were used to create this post.

sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.3.1 (2023-06-16)
 os       Ubuntu 22.04.3 LTS
 system   x86_64, linux-gnu
 ui       X11
 language nl_BE:nl
 collate  nl_BE.UTF-8
 ctype    nl_BE.UTF-8
 tz       Europe/Brussels
 date     2023-08-30
 pandoc   3.1.1 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/ (via rmarkdown)

─ Packages ───────────────────────────────────────────────────────────────────
 package          * version    date (UTC) lib source
 abind              1.4-5      2016-07-21 [1] CRAN (R 4.3.0)
 class              7.3-22     2023-05-03 [4] CRAN (R 4.3.1)
 classInt           0.4-9      2023-02-28 [1] CRAN (R 4.3.1)
 cli                3.6.1      2023-03-23 [1] CRAN (R 4.3.0)
 codetools          0.2-19     2023-02-01 [1] CRAN (R 4.3.0)
 colorspace         2.1-0      2023-01-23 [1] CRAN (R 4.3.0)
 crosstalk          1.2.0      2021-11-04 [1] CRAN (R 4.3.0)
 curl               5.0.1      2023-06-07 [1] CRAN (R 4.3.0)
 DBI                1.1.3      2022-06-18 [1] CRAN (R 4.3.0)
 deldir             1.0-9      2023-05-17 [1] CRAN (R 4.3.0)
 digest             0.6.32     2023-06-26 [1] CRAN (R 4.3.1)
 dplyr            * 1.1.2      2023-04-20 [1] CRAN (R 4.3.0)
 e1071              1.7-13     2023-02-01 [1] CRAN (R 4.3.1)
 ellipsis           0.3.2      2021-04-29 [1] CRAN (R 4.3.0)
 evaluate           0.21       2023-05-05 [1] CRAN (R 4.3.0)
 fansi              1.0.4      2023-01-22 [1] CRAN (R 4.3.0)
 farver             2.1.1      2022-07-06 [1] CRAN (R 4.3.0)
 fastmap            1.1.1      2023-02-24 [1] CRAN (R 4.3.0)
 generics           0.1.3      2022-07-05 [1] CRAN (R 4.3.0)
 ggplot2            3.4.2      2023-04-03 [1] CRAN (R 4.3.0)
 glue               1.6.2      2022-02-24 [1] CRAN (R 4.3.0)
 goftest            1.2-3      2021-10-07 [1] CRAN (R 4.3.1)
 gtable             0.3.3      2023-03-21 [1] CRAN (R 4.3.0)
 htmltools          0.5.5      2023-03-23 [1] CRAN (R 4.3.0)
 htmlwidgets        1.6.2      2023-03-17 [1] CRAN (R 4.3.0)
 httr2              0.2.3      2023-05-08 [1] CRAN (R 4.3.0)
 jsonlite           1.8.7      2023-06-29 [1] CRAN (R 4.3.1)
 KernSmooth         2.23-21    2023-05-03 [1] CRAN (R 4.3.0)
 knitr              1.43       2023-05-25 [1] CRAN (R 4.3.0)
 labeling           0.4.2      2020-10-20 [1] CRAN (R 4.3.0)
 lattice            0.21-8     2023-04-05 [4] CRAN (R 4.3.0)
 leaflet          * 2.1.2      2023-03-10 [1] CRAN (R 4.3.0)
 lifecycle          1.0.3      2022-10-07 [1] CRAN (R 4.3.0)
 lubridate          1.9.2.9000 2023-05-15 [1] https://inbo.r-universe.dev (R 4.3.0)
 magrittr           2.0.3      2022-03-30 [1] CRAN (R 4.3.0)
 mapproj            1.2.11     2023-01-12 [1] CRAN (R 4.3.1)
 maps               3.4.1      2022-10-30 [1] CRAN (R 4.3.1)
 MASS             * 7.3-60     2023-05-04 [4] CRAN (R 4.3.1)
 Matrix             1.5-4.1    2023-05-18 [1] CRAN (R 4.3.0)
 mgcv               1.8-42     2023-03-02 [1] CRAN (R 4.3.0)
 munsell            0.5.0      2018-06-12 [1] CRAN (R 4.3.0)
 nlme               3.1-162    2023-01-31 [1] CRAN (R 4.3.0)
 osmdata            0.2.4.003  2023-08-13 [1] https://ropensci.r-universe.dev (R 4.3.1)
 osmplotr         * 0.3.3.037  2023-08-13 [1] https://ropensci.r-universe.dev (R 4.3.1)
 pillar             1.9.0      2023-03-22 [1] CRAN (R 4.3.0)
 pkgconfig          2.0.3      2019-09-22 [1] CRAN (R 4.3.0)
 polyclip           1.10-4     2022-10-20 [1] CRAN (R 4.3.1)
 proxy              0.4-27     2022-06-09 [1] CRAN (R 4.3.1)
 R6                 2.5.1      2021-08-19 [1] CRAN (R 4.3.0)
 rappdirs           0.3.3      2021-01-31 [1] CRAN (R 4.3.0)
 Rcpp               1.0.10     2023-01-22 [1] CRAN (R 4.3.0)
 rlang              1.1.1      2023-04-28 [1] CRAN (R 4.3.0)
 rmarkdown          2.23       2023-07-01 [1] CRAN (R 4.3.1)
 rpart              4.1.19     2022-10-21 [1] CRAN (R 4.3.0)
 rstudioapi         0.14       2022-08-22 [1] CRAN (R 4.3.0)
 scales             1.2.1      2022-08-20 [1] CRAN (R 4.3.0)
 sessioninfo        1.2.2      2021-12-06 [1] CRAN (R 4.3.0)
 sf               * 1.0-13     2023-05-24 [1] CRAN (R 4.3.0)
 sp                 2.0-0      2023-06-22 [1] CRAN (R 4.3.1)
 spatstat           3.0-6      2023-05-17 [1] CRAN (R 4.3.1)
 spatstat.data      3.0-1      2023-03-12 [1] CRAN (R 4.3.1)
 spatstat.explore   3.2-1      2023-05-13 [1] CRAN (R 4.3.1)
 spatstat.geom      3.2-1      2023-05-09 [1] CRAN (R 4.3.0)
 spatstat.linnet    3.1-1      2023-05-15 [1] CRAN (R 4.3.1)
 spatstat.model     3.2-4      2023-05-15 [1] CRAN (R 4.3.1)
 spatstat.random    3.1-5      2023-05-11 [1] CRAN (R 4.3.1)
 spatstat.sparse    3.0-2      2023-06-25 [1] CRAN (R 4.3.1)
 spatstat.utils     3.0-3      2023-05-09 [1] CRAN (R 4.3.1)
 tensor             1.5        2012-05-05 [1] CRAN (R 4.3.1)
 tibble             3.2.1      2023-03-20 [1] CRAN (R 4.3.0)
 tidyselect         1.2.0      2022-10-10 [1] CRAN (R 4.3.0)
 timechange         0.2.0      2023-01-11 [1] CRAN (R 4.3.0)
 units              0.8-2      2023-04-27 [1] CRAN (R 4.3.0)
 utf8               1.2.3      2023-01-31 [1] CRAN (R 4.3.0)
 vctrs              0.6.3      2023-06-14 [1] CRAN (R 4.3.0)
 withr              2.5.0      2022-03-03 [1] CRAN (R 4.3.0)
 wk               * 0.7.3      2023-05-06 [1] CRAN (R 4.3.1)
 xfun               0.39       2023-04-20 [1] CRAN (R 4.3.0)
 xml2               1.3.4      2023-04-27 [1] CRAN (R 4.3.0)
 yaml               2.3.7      2023-01-23 [1] CRAN (R 4.3.0)

 [1] /home/thierry/R/x86_64-pc-linux-gnu-library/4.3
 [2] /usr/local/lib/R/site-library
 [3] /usr/lib/R/site-library
 [4] /usr/lib/R/library

──────────────────────────────────────────────────────────────────────────────