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()

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.3.1 (2023-06-16)
#>  os       Ubuntu 23.04
#>  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     2023-08-16
#>  pandoc   2.17.1.1 @ /usr/bin/ (via rmarkdown)
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#>  ! package            * version date (UTC) lib source
#>  P base64enc            0.1-3   2015-07-28 [?] RSPM (R 4.3.0)
#>  P cachem               1.0.8   2023-05-01 [?] RSPM (R 4.3.0)
#>  P callr                3.7.3   2022-11-02 [?] RSPM (R 4.3.0)
#>  P class                7.3-22  2023-05-03 [?] RSPM (R 4.3.0)
#>  P classInt             0.4-9   2023-02-28 [?] CRAN (R 4.3.0)
#>  P cli                  3.6.1   2023-03-23 [?] RSPM (R 4.3.0)
#>  P codetools            0.2-19  2023-02-01 [?] CRAN (R 4.3.1)
#>  P colorspace           2.1-0   2023-01-23 [?] RSPM (R 4.3.0)
#>  P crayon               1.5.2   2022-09-29 [?] RSPM (R 4.3.0)
#>  P crosstalk            1.2.0   2021-11-04 [?] RSPM (R 4.3.0)
#>  P crsuggest            0.4     2022-07-06 [?] RSPM (R 4.3.0)
#>  P DBI                  1.1.3   2022-06-18 [?] RSPM (R 4.3.0)
#>  P devtools             2.4.5   2022-10-11 [?] RSPM (R 4.3.0)
#>  P digest               0.6.33  2023-07-07 [?] RSPM (R 4.3.0)
#>  P dplyr              * 1.1.2   2023-04-20 [?] RSPM (R 4.3.0)
#>  P e1071                1.7-13  2023-02-01 [?] CRAN (R 4.3.0)
#>  P ellipsis             0.3.2   2021-04-29 [?] RSPM (R 4.3.0)
#>  P evaluate             0.21    2023-05-05 [?] RSPM (R 4.3.0)
#>  P extrafont            0.19    2023-01-18 [?] RSPM (R 4.3.0)
#>  P extrafontdb          1.0     2012-06-11 [?] RSPM (R 4.3.0)
#>  P fansi                1.0.4   2023-01-22 [?] RSPM (R 4.3.0)
#>  P farver               2.1.1   2022-07-06 [?] RSPM (R 4.3.0)
#>  P fastmap              1.1.1   2023-02-24 [?] RSPM (R 4.3.0)
#>  P forcats            * 1.0.0   2023-01-29 [?] RSPM (R 4.3.0)
#>  P fs                   1.6.3   2023-07-20 [?] RSPM (R 4.3.1)
#>  P generics             0.1.3   2022-07-05 [?] RSPM (R 4.3.0)
#>  P ggfx               * 1.0.1   2022-08-22 [?] RSPM (R 4.3.1)
#>  P ggplot2            * 3.4.2   2023-04-03 [?] RSPM (R 4.3.0)
#>  P ggpmthemes         * 0.0.2   2023-04-24 [?] Github (PMassicotte/ggpmthemes@993d61e)
#>  P glue                 1.6.2   2022-02-24 [?] RSPM (R 4.3.0)
#>  P gtable               0.3.3   2023-03-21 [?] RSPM (R 4.3.0)
#>  P hms                  1.1.3   2023-03-21 [?] RSPM (R 4.3.0)
#>  P htmltools            0.5.6   2023-08-10 [?] RSPM (R 4.3.1)
#>  P htmlwidgets          1.6.2   2023-03-17 [?] RSPM (R 4.3.0)
#>  P httpuv               1.6.11  2023-05-11 [?] RSPM (R 4.3.0)
#>  P httr                 1.4.6   2023-05-08 [?] RSPM (R 4.3.0)
#>  P jsonlite             1.8.7   2023-06-29 [?] RSPM (R 4.3.0)
#>  P KernSmooth           2.23-22 2023-07-10 [?] RSPM (R 4.3.1)
#>  P knitr                1.43    2023-05-25 [?] RSPM (R 4.3.1)
#>  P later                1.3.1   2023-05-02 [?] RSPM (R 4.3.0)
#>  P lattice              0.21-8  2023-04-05 [?] RSPM (R 4.3.0)
#>  P leafem               0.2.0   2022-04-16 [?] RSPM (R 4.3.0)
#>  P leaflet              2.1.2   2023-03-10 [?] RSPM (R 4.3.0)
#>  P lifecycle            1.0.3   2022-10-07 [?] RSPM (R 4.3.0)
#>  P lubridate          * 1.9.2   2023-02-10 [?] RSPM (R 4.3.0)
#>  P magick               2.7.5   2023-08-07 [?] RSPM (R 4.3.1)
#>  P magrittr             2.0.3   2022-03-30 [?] RSPM (R 4.3.0)
#>  P mapview              2.11.0  2022-04-16 [?] RSPM (R 4.3.0)
#>  P memoise              2.0.1   2021-11-26 [?] RSPM (R 4.3.0)
#>  P mime                 0.12    2021-09-28 [?] RSPM (R 4.3.0)
#>  P miniUI               0.1.1.1 2018-05-18 [?] RSPM (R 4.3.0)
#>  P munsell              0.5.0   2018-06-12 [?] RSPM (R 4.3.0)
#>  P pillar               1.9.0   2023-03-22 [?] RSPM (R 4.3.0)
#>  P pkgbuild             1.4.2   2023-06-26 [?] RSPM (R 4.3.1)
#>  P pkgconfig            2.0.3   2019-09-22 [?] RSPM (R 4.3.0)
#>  P pkgload              1.3.2.1 2023-07-08 [?] RSPM (R 4.3.0)
#>  P png                  0.1-8   2022-11-29 [?] RSPM
#>  P prettyunits          1.1.1   2020-01-24 [?] RSPM (R 4.3.0)
#>  P processx             3.8.2   2023-06-30 [?] RSPM (R 4.3.0)
#>  P profvis              0.3.8   2023-05-02 [?] RSPM (R 4.3.0)
#>  P promises             1.2.1   2023-08-10 [?] RSPM (R 4.3.1)
#>  P proxy                0.4-27  2022-06-09 [?] CRAN (R 4.3.0)
#>  P ps                   1.7.5   2023-04-18 [?] RSPM (R 4.3.0)
#>  P purrr              * 1.0.2   2023-08-10 [?] RSPM (R 4.3.1)
#>  P R6                   2.5.1   2021-08-19 [?] RSPM (R 4.3.0)
#>  P ragg                 1.2.5   2023-01-12 [?] CRAN (R 4.3.0)
#>  P raster               3.6-23  2023-07-04 [?] RSPM (R 4.3.1)
#>  P Rcpp                 1.0.11  2023-07-06 [?] RSPM (R 4.3.1)
#>  P readr              * 2.1.4   2023-02-10 [?] RSPM (R 4.3.0)
#>  P remotes              2.4.2.1 2023-07-18 [?] RSPM (R 4.3.0)
#>  P renv                 1.0.1   2023-08-10 [?] RSPM (R 4.3.1)
#>  P rlang                1.1.1   2023-04-28 [?] RSPM (R 4.3.0)
#>  P rmarkdown            2.23    2023-07-01 [?] RSPM (R 4.3.0)
#>  P rnaturalearth        0.3.3   2023-06-06 [?] RSPM (R 4.3.1)
#>    rnaturalearthhires   0.2.1   2023-08-15 [1] Github (ropensci/rnaturalearthhires@c3785a8)
#>  P rstudioapi           0.15.0  2023-07-07 [?] RSPM (R 4.3.1)
#>  P Rttf2pt1             1.3.12  2023-01-22 [?] RSPM (R 4.3.0)
#>  P s2                   1.1.4   2023-05-17 [?] RSPM (R 4.3.0)
#>  P satellite            1.0.4   2021-10-12 [?] RSPM (R 4.3.0)
#>  P scales               1.2.1   2022-08-20 [?] RSPM (R 4.3.0)
#>  P sessioninfo          1.2.2   2021-12-06 [?] RSPM (R 4.3.0)
#>  P sf                 * 1.0-14  2023-07-11 [?] CRAN (R 4.3.1)
#>  P shiny                1.7.4.1 2023-07-06 [?] RSPM (R 4.3.1)
#>  P sp                   2.0-0   2023-06-22 [?] RSPM (R 4.3.1)
#>  P stringi              1.7.12  2023-01-11 [?] CRAN (R 4.3.0)
#>  P stringr            * 1.5.0   2022-12-02 [?] CRAN (R 4.3.0)
#>  P systemfonts          1.0.4   2022-02-11 [?] RSPM (R 4.3.0)
#>  P terra                1.7-39  2023-06-23 [?] CRAN (R 4.3.1)
#>  P textshaping          0.3.6   2021-10-13 [?] RSPM (R 4.3.0)
#>  P tibble             * 3.2.1   2023-03-20 [?] RSPM (R 4.3.0)
#>  P tidyr              * 1.3.0   2023-01-24 [?] RSPM (R 4.3.0)
#>  P tidyselect           1.2.0   2022-10-10 [?] RSPM (R 4.3.0)
#>  P tidyverse          * 2.0.0   2023-02-22 [?] RSPM (R 4.3.0)
#>  P timechange           0.2.0   2023-01-11 [?] RSPM (R 4.3.0)
#>  P tzdb                 0.4.0   2023-05-12 [?] RSPM (R 4.3.0)
#>  P units                0.8-3   2023-08-10 [?] RSPM (R 4.3.1)
#>  P urlchecker           1.0.1   2021-11-30 [?] RSPM (R 4.3.0)
#>  P usethis              2.2.2   2023-07-06 [?] RSPM (R 4.3.1)
#>  P utf8                 1.2.3   2023-01-31 [?] RSPM (R 4.3.0)
#>  P vctrs                0.6.3   2023-06-14 [?] RSPM (R 4.3.0)
#>  P webshot              0.5.5   2023-06-26 [?] RSPM (R 4.3.1)
#>  P withr                2.5.0   2022-03-03 [?] RSPM (R 4.3.0)
#>  P wk                   0.7.3   2023-05-06 [?] RSPM (R 4.3.0)
#>  P xfun                 0.40    2023-08-09 [?] RSPM (R 4.3.1)
#>  P xtable               1.8-4   2019-04-21 [?] RSPM (R 4.3.0)
#>  P yaml                 2.3.7   2023-01-23 [?] RSPM (R 4.3.0)
#> 
#>  [1] /media/work/r-blog/renv/library/R-4.3/x86_64-pc-linux-gnu
#>  [2] /home/filoche/.cache/R/renv/sandbox/R-4.3/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.