Separating/exploding spatial features with R

R
rspatial
Geospatial
Author

Philippe Massicotte

Published

August 15, 2023

It has been a while since I posted something! But today I wanted to quickly experiment and create a map where I could separate/explode the spatial geometries. Let’s first download the polygon data for Canada.

library(sf)
library(tidyverse)

canada <- rnaturalearth::ne_states(country = "canada", returnclass = "sf") |>
  st_make_valid()
#> 
#> ── R CMD build ─────────────────────────────────────────────────────────────────
#> * checking for file ‘/tmp/RtmpwyVqRL/remotes2fbb24690b6b27/ropensci-rnaturalearthhires-dd1e210/DESCRIPTION’ ... OK
#> * preparing ‘rnaturalearthhires’:
#> * checking DESCRIPTION meta-information ... OK
#> * checking for LF line-endings in source and make files and shell scripts
#> * checking for empty or unneeded directories
#> * building ‘rnaturalearthhires_1.0.0.9000.tar.gz’

As we can see, there are three different regions.

canada |>
  distinct(region)
#>            region
#> 1  Western Canada
#> 2  Eastern Canada
#> 3 Northern Canada

These regions can be visualized using ggplot2 and sf.

# Get a good CRS for Canada
crsuggest::suggest_crs(canada)
#> # A tibble: 10 × 6
#>    crs_code crs_name                        crs_type crs_gcs crs_units crs_proj4
#>    <chr>    <chr>                           <chr>      <dbl> <chr>     <chr>    
#>  1 5931     WGS 84 / EPSG Arctic Regional … project…    4326 m         +proj=lc…
#>  2 3979     NAD83(CSRS) / Canada Atlas Lam… project…    4617 m         +proj=lc…
#>  3 3978     NAD83 / Canada Atlas Lambert    project…    4269 m         +proj=lc…
#>  4 3348     NAD83(CSRS) / Statistics Canad… project…    4617 m         +proj=lc…
#>  5 3347     NAD83 / Statistics Canada Lamb… project…    4269 m         +proj=lc…
#>  6 5926     WGS 84 / EPSG Arctic Regional … project…    4326 m         +proj=lc…
#>  7 5921     WGS 84 / EPSG Arctic Regional … project…    4326 m         +proj=lc…
#>  8 6350     NAD83(2011) / Conus Albers      project…    6318 m         +proj=ae…
#>  9 5072     NAD83(NSRS2007) / Conus Albers  project…    4759 m         +proj=ae…
#> 10 5071     NAD83(HARN) / Conus Albers      project…    4152 m         +proj=ae…

canada <- canada |>
  st_transform(5931)

canada |>
  ggplot(aes(fill = region)) +
  geom_sf()

With this following code, we can find the centroid of each region and shift the centers of the new polygons.

canada_exploded <- canada |>
  group_by(region) |>
  mutate(region_centroid = st_centroid(st_union(geometry))) |>
  ungroup() |>
  mutate(geometry = (geometry - region_centroid) * 0.9 + region_centroid)

st_crs(canada_exploded)
#> Coordinate Reference System: NA

As seen above, for a reason I do not know, we have lost the CRS after the operation, so I have to set it back before visualizing it.

canada_exploded <- canada_exploded |>
  st_set_crs(5931)

canada_exploded |>
  ggplot(aes(fill = region)) +
  geom_sf()

Bonus: if we want to get a little bit more fancy, we can add shadows with ggfx:

library(ggfx)

canada_exploded |>
  ggplot(aes(fill = region)) +
  with_shadow(
    geom_sf(),
    sigma = 5,
    x_offset = 20,
    y_offset = 20
  ) +
  theme(
    legend.position = "none"
  )

Session info
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.0 (2024-04-24)
#>  os       Ubuntu 24.04 LTS
#>  system   x86_64, linux-gnu
#>  ui       X11
#>  language en_CA:en
#>  collate  en_CA.UTF-8
#>  ctype    en_CA.UTF-8
#>  tz       America/Toronto
#>  date     2024-05-02
#>  pandoc   3.1.3 @ /usr/bin/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#>  ! package            * version    date (UTC) lib source
#>  P base64enc            0.1-3      2015-07-28 [?] RSPM (R 4.4.0)
#>  P cachem               1.0.8      2023-05-01 [?] RSPM (R 4.4.0)
#>  P callr                3.7.6      2024-03-25 [?] RSPM (R 4.4.0)
#>  P class                7.3-22     2023-05-03 [?] CRAN (R 4.4.0)
#>  P classInt             0.4-10     2023-09-05 [?] RSPM (R 4.4.0)
#>  P cli                  3.6.2      2023-12-11 [?] RSPM (R 4.4.0)
#>  P codetools            0.2-20     2024-03-31 [?] CRAN (R 4.4.0)
#>  P colorspace           2.1-0      2023-01-23 [?] RSPM (R 4.4.0)
#>  P crosstalk            1.2.1      2023-11-23 [?] RSPM (R 4.4.0)
#>  P crsuggest            0.4        2022-07-06 [?] RSPM (R 4.4.0)
#>  P curl                 5.2.1      2024-03-01 [?] RSPM (R 4.4.0)
#>  P DBI                  1.2.2      2024-02-16 [?] RSPM (R 4.4.0)
#>  P desc                 1.4.3      2023-12-10 [?] RSPM (R 4.4.0)
#>  P devtools             2.4.5      2022-10-11 [?] RSPM
#>  P digest               0.6.35     2024-03-11 [?] RSPM (R 4.4.0)
#>  P dplyr              * 1.1.4      2023-11-17 [?] RSPM (R 4.4.0)
#>  P e1071                1.7-14     2023-12-06 [?] RSPM (R 4.4.0)
#>  P ellipsis             0.3.2      2021-04-29 [?] RSPM (R 4.4.0)
#>  P evaluate             0.23       2023-11-01 [?] RSPM (R 4.4.0)
#>  P extrafont            0.19       2023-01-18 [?] RSPM (R 4.4.0)
#>  P extrafontdb          1.0        2012-06-11 [?] RSPM (R 4.4.0)
#>  P fansi                1.0.6      2023-12-08 [?] RSPM (R 4.4.0)
#>  P farver               2.1.1      2022-07-06 [?] CRAN (R 4.4.0)
#>  P fastmap              1.1.1      2023-02-24 [?] RSPM (R 4.4.0)
#>  P forcats            * 1.0.0      2023-01-29 [?] RSPM (R 4.4.0)
#>  P fs                   1.6.4      2024-04-25 [?] CRAN (R 4.4.0)
#>  P generics             0.1.3      2022-07-05 [?] RSPM (R 4.4.0)
#>  P ggfx               * 1.0.1      2022-08-22 [?] RSPM (R 4.4.0)
#>  P ggplot2            * 3.5.1      2024-04-23 [?] RSPM (R 4.4.0)
#>  P ggpmthemes         * 0.0.2      2024-05-02 [?] Github (pmassicotte/ggpmthemes@993d61e)
#>  P glue                 1.7.0      2024-01-09 [?] RSPM (R 4.4.0)
#>  P gtable               0.3.5      2024-04-22 [?] RSPM (R 4.4.0)
#>  P hms                  1.1.3      2023-03-21 [?] RSPM (R 4.4.0)
#>  P htmltools            0.5.8.1    2024-04-04 [?] RSPM (R 4.4.0)
#>  P htmlwidgets          1.6.4      2023-12-06 [?] RSPM
#>  P httpuv               1.6.15     2024-03-26 [?] RSPM (R 4.4.0)
#>  P httr                 1.4.7      2023-08-15 [?] RSPM (R 4.4.0)
#>  P jsonlite             1.8.8      2023-12-04 [?] RSPM (R 4.4.0)
#>  P KernSmooth           2.23-22    2023-07-10 [?] CRAN (R 4.4.0)
#>  P knitr                1.46       2024-04-06 [?] RSPM (R 4.4.0)
#>  P later                1.3.2      2023-12-06 [?] RSPM (R 4.4.0)
#>  P lattice              0.22-6     2024-03-20 [?] CRAN (R 4.4.0)
#>  P leafem               0.2.3      2023-09-17 [?] RSPM (R 4.4.0)
#>  P leaflet              2.2.2      2024-03-26 [?] RSPM (R 4.4.0)
#>  P lifecycle            1.0.4      2023-11-07 [?] RSPM (R 4.4.0)
#>  P lubridate          * 1.9.3      2023-09-27 [?] RSPM (R 4.4.0)
#>  P magick               2.8.3      2024-02-18 [?] RSPM (R 4.4.0)
#>  P magrittr             2.0.3      2022-03-30 [?] RSPM (R 4.4.0)
#>  P mapview              2.11.2     2023-10-13 [?] RSPM (R 4.4.0)
#>  P memoise              2.0.1      2021-11-26 [?] RSPM (R 4.4.0)
#>  P mime                 0.12       2021-09-28 [?] RSPM (R 4.4.0)
#>  P miniUI               0.1.1.1    2018-05-18 [?] RSPM (R 4.4.0)
#>  P munsell              0.5.1      2024-04-01 [?] CRAN (R 4.4.0)
#>  P pillar               1.9.0      2023-03-22 [?] RSPM (R 4.4.0)
#>  P pkgbuild             1.4.4      2024-03-17 [?] RSPM (R 4.4.0)
#>  P pkgconfig            2.0.3      2019-09-22 [?] RSPM (R 4.4.0)
#>  P pkgload              1.3.4      2024-01-16 [?] RSPM
#>  P png                  0.1-8      2022-11-29 [?] RSPM (R 4.4.0)
#>  P processx             3.8.4      2024-03-16 [?] RSPM (R 4.4.0)
#>  P profvis              0.3.8      2023-05-02 [?] RSPM
#>  P promises             1.3.0      2024-04-05 [?] RSPM (R 4.4.0)
#>  P proxy                0.4-27     2022-06-09 [?] RSPM (R 4.4.0)
#>  P ps                   1.7.6      2024-01-18 [?] RSPM (R 4.4.0)
#>  P purrr              * 1.0.2      2023-08-10 [?] RSPM (R 4.4.0)
#>  P quarto             * 1.4        2024-03-06 [?] RSPM
#>  P R.cache              0.16.0     2022-07-21 [?] RSPM
#>  P R.methodsS3          1.8.2      2022-06-13 [?] RSPM
#>  P R.oo                 1.26.0     2024-01-24 [?] RSPM
#>  P R.utils              2.12.3     2023-11-18 [?] RSPM
#>  P R6                   2.5.1      2021-08-19 [?] RSPM (R 4.4.0)
#>  P ragg                 1.3.0      2024-03-13 [?] RSPM
#>  P raster               3.6-26     2023-10-14 [?] RSPM (R 4.4.0)
#>  P Rcpp                 1.0.12     2024-01-09 [?] RSPM (R 4.4.0)
#>  P readr              * 2.1.5      2024-01-10 [?] RSPM (R 4.4.0)
#>  P remotes              2.5.0      2024-03-17 [?] RSPM
#>  P renv                 1.0.7      2024-04-11 [?] RSPM (R 4.4.0)
#>  P rlang                1.1.3      2024-01-10 [?] RSPM (R 4.4.0)
#>  P rmarkdown            2.26       2024-03-05 [?] RSPM (R 4.4.0)
#>  P rnaturalearth        1.0.1      2023-12-15 [?] RSPM
#>    rnaturalearthhires   1.0.0.9000 2024-05-02 [1] Github (ropensci/rnaturalearthhires@dd1e210)
#>  P rstudioapi           0.16.0     2024-03-24 [?] RSPM
#>  P Rttf2pt1             1.3.12     2023-01-22 [?] RSPM (R 4.4.0)
#>  P s2                   1.1.6      2023-12-19 [?] RSPM (R 4.4.0)
#>  P satellite            1.0.5      2024-02-10 [?] RSPM (R 4.4.0)
#>  P scales               1.3.0      2023-11-28 [?] CRAN (R 4.4.0)
#>  P sessioninfo          1.2.2      2021-12-06 [?] RSPM
#>  P sf                 * 1.0-16     2024-03-24 [?] RSPM (R 4.4.0)
#>  P shiny                1.8.1.1    2024-04-02 [?] RSPM (R 4.4.0)
#>  P sp                   2.1-4      2024-04-30 [?] RSPM
#>  P stringi              1.8.3      2023-12-11 [?] RSPM (R 4.4.0)
#>  P stringr            * 1.5.1      2023-11-14 [?] RSPM (R 4.4.0)
#>  P styler             * 1.10.3     2024-04-07 [?] RSPM
#>  P systemfonts          1.0.6      2024-03-07 [?] RSPM (R 4.4.0)
#>  P terra                1.7-71     2024-01-31 [?] CRAN (R 4.4.0)
#>  P textshaping          0.3.7      2023-10-09 [?] RSPM
#>  P tibble             * 3.2.1      2023-03-20 [?] RSPM (R 4.4.0)
#>  P tidyr              * 1.3.1      2024-01-24 [?] RSPM (R 4.4.0)
#>  P tidyselect           1.2.1      2024-03-11 [?] RSPM (R 4.4.0)
#>  P tidyverse          * 2.0.0      2023-02-22 [?] RSPM (R 4.4.0)
#>  P timechange           0.3.0      2024-01-18 [?] RSPM (R 4.4.0)
#>  P tzdb                 0.4.0      2023-05-12 [?] RSPM (R 4.4.0)
#>  P units                0.8-5      2023-11-28 [?] RSPM (R 4.4.0)
#>  P urlchecker           1.0.1      2021-11-30 [?] RSPM
#>  P usethis              2.2.3      2024-02-19 [?] RSPM
#>  P utf8                 1.2.4      2023-10-22 [?] RSPM (R 4.4.0)
#>  P vctrs                0.6.5      2023-12-01 [?] RSPM (R 4.4.0)
#>  P withr                3.0.0      2024-01-16 [?] RSPM (R 4.4.0)
#>  P wk                   0.9.1      2023-11-29 [?] RSPM (R 4.4.0)
#>  P xfun                 0.43       2024-03-25 [?] RSPM (R 4.4.0)
#>  P xtable               1.8-4      2019-04-21 [?] RSPM (R 4.4.0)
#>  P yaml                 2.3.8      2023-12-11 [?] RSPM (R 4.4.0)
#> 
#>  [1] /tmp/RtmpwyVqRL/renv-use-libpath-2fbb2417a8ef72
#>  [2] /home/filoche/.cache/R/renv/sandbox/linux-ubuntu-noble/R-4.4/x86_64-pc-linux-gnu/a71ef467
#> 
#>  P ── Loaded and on-disk path mismatch.
#> 
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Citation

BibTeX citation:
@online{massicotte2023,
  author = {Massicotte, Philippe},
  title = {Separating/Exploding Spatial Features with {R}},
  date = {2023-08-15},
  url = {https://www.pmassicotte.com/posts/2023-08-15-map-explode},
  langid = {en}
}
For attribution, please cite this work as:
Massicotte, Philippe. 2023. “Separating/Exploding Spatial Features with R.” August 15, 2023. https://www.pmassicotte.com/posts/2023-08-15-map-explode.