Choosing the right geographic projection with the crsuggest R package

R
Geospatial
Author

Philippe Massicotte

Published

November 12, 2021

When creating maps, choosing an appropriate geographical projection is often a difficult task (at least for me). There are plenty of projections to choose from, and none can be qualified as the best one. It all depends on what you are trying to achieve. Websites like the projection wizard website offer a playground to experiment with different projections and how they look like depending on where you are looking at on the globe.

A medieval depiction of the Ecumene (1482, Johannes Schnitzer, engraver), constructed after the coordinates in Ptolemy’s Geography and using his second map projection

Image from: https://en.wikipedia.org/wiki/Map_projection

The goal of this blog post is not to go into details and consideration on how to choose a good projection (it is out of my expertise), but rather present a quick overview of the crsuggest R package that can help to find a projection suited for the data to be displayed.

# Download the Greenland shapefile
map <- ne_countries(country = "greenland", returnclass = "sf", scale = "medium")

# Looks at the projection
st_crs(map)$proj4string
#> [1] "+proj=longlat +datum=WGS84 +no_defs"

We can see that WGS84 is used as the reference coordinate system. Plotting the shapefile immediately shows that the result is somewhat distorted.

p1 <- ggplot() +
  geom_sf(data = map)

p1

Time to look at the crsuggest package. The function suggest_crs() takes a spatial dataset as inputs (here the map object) and return a list (n = 10 by default) of suggested coordinate systems in a tibble.

suggested_crs <- suggest_crs(map, limit = 3)
suggested_crs
#> # A tibble: 3 × 6
#>   crs_code crs_name                         crs_type crs_gcs crs_units crs_proj4
#>   <chr>    <chr>                            <chr>      <dbl> <chr>     <chr>    
#> 1 5922     WGS 84 / EPSG Arctic Regional z… project…    4326 m         +proj=lc…
#> 2 6054     GR96 / EPSG Arctic zone 3-31     project…    4747 m         +proj=lc…
#> 3 6051     GR96 / EPSG Arctic zone 2-18     project…    4747 m         +proj=lc…

Let’s make some plots using the suggested CRS.

plot_map <- function(crs, map) {
  ggplot() +
    geom_sf(data = map) +
    coord_sf(crs = as.numeric(crs)) +
    labs(
      title = paste("CRS:", crs)
    )
}

maps <- lapply(suggested_crs$crs_code, plot_map, map = map)

We can see that the projected maps look more accurate than the original map.

wrap_plots(maps, ncol = 3)

This is even more obvious when they are compared side by side.

p2 <- ggplot() +
  geom_sf(data = map) +
  coord_sf(crs = 5922)

p1 + p2

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