How to draw a cartogram in r without zip code, longitude and latitude?

87 Views Asked by At

I want to make a cartogram with data from my country Suriname. This diagram should show the location on the map together with the number of the schools. The only data I have is:

District Ressort Coordinaten Schoolcode
Paramaribo Beekhuizen 5°30'29,88"NB, 55°10'44,04"WL A1
Paramaribo Beekhuizen 5°30'29,88"NB, 55°10'44,04"WL A2
Paramaribo Centrum 5°30'29,9"NB, 55°10'44,0"WL A3
Paramaribo Beekhuizen 5°30'29,88"NB, 55°10'44,04"WL A4
Paramaribo Welgelegen 5°50'33"NB, 55°13'7"WL A5
Wanica Nieuwe Grond 5°45'NB, 55°13'WL A6
Wanica Domburg 5°42'NB, 55°5'WL A7
Wanica Domburg 5°42'NB, 55°5'WL A8

I checked for instruction video and found instructions about constructing a cartogram with zip codes and with the longitude and latitude. Is it possible to use this data in r to construct a cartogram? If yes, can you give me some instruction how to do that? If the answer is no, is it possible to convert this column into the longitude and latitude or even zipcode of data? If yes, how can I do that?

Thank you in advance.

1

There are 1 best solutions below

1
On

Here is something that should get you started; additional comments are inline.

Load necessary libraries

# Load libraries
library(tidyverse)
library(magrittr)
library(sf)

Download Suriname shape files

# Download Suriname shape files of country, district and resort boundaries
# Source: https://data.humdata.org/dataset/suriname-administrative-level-0-1-and-2-boundaries
url <- "https://data.humdata.org/dataset/ab35e673-76f2-43e5-a6a4-a5b81f9e093c/resource/fd31ebfd-bf77-4b7d-902f-3ea3a9c2d7a2/download/sur_adm_2017_shp.zip"
download.file(url, "suriname_data.zip")
unzip("suriname_data.zip", exdir = "data")

Data are stored in folder ./data. The ZIP file also contains a PDF with metadata information. I suggest taking a look.

Read Suriname district shapefile

# Read shapefile of Suriname districts
# Note: Geodetic CRS = WGS84
suriname_district <- st_read("data/sur_admbnda_adm1_2017.shp")

Parse local data

# Define custom function to parse coordinates from your data.frame
parse_coordinaten <- function(x) {

    x %>%
    str_remove_all("(NB|WL)") %>%        # Remove NB and WL suffixes
    str_split(", ") %>%                  # Split into lat/long string
    map(~ .x %>%
        str_replace_all(",", ".") %>%    # Replace , with . decimal separator
        str_split("[^(\\d|\\.)]") %>%    # Split each lat/long on non-digit char
        map_dbl(function(w) w %>%        # Convert deg/min/sec to fractional degree
            as.numeric() %>%
            multiply_by(c(1, 1/60, 1/3600)) %>%
            sum(na.rm = TRUE)
        ) %>%
        multiply_by(c(1, -1)) %>%        # Multiply long by -1 since west of prime meridian 
        setNames(c("lat", "lon")) %>%   
        bind_rows()
    ) %>%
        bind_rows()
}

# Read data; I assume you have a `data.frame` named `df` 
# Note: `dput(df)` included in the appendix
data <- df %>%
    mutate(Coordinaten = map(Coordinaten, parse_coordinaten)) %>%
    unnest(Coordinaten) %>%
    st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
    mutate(label = paste(District, Ressort, Schoolcode, sep = "<br>"))

Plot

# Plot using `leaflet`
library(leaflet)
pal <- colorFactor("Spectral", levels = suriname_district$ADM1_NL)
leaflet() %>%
    addTiles() %>% 
    addPolygons(
        fillColor = ~pal(ADM1_NL),
        fillOpacity = 0.6,
        weight = 0,
        data = suriname_district) %>%
    addMarkers(
        data = data,
        label = ~map(label, htmltools::HTML))

enter image description here

leaflet allows for a lot of customisation; for example, you can tweak the marker labels, add resort boundaries, etc.


Appendix: Sample data

df <- structure(list(District = c("Paramaribo", "Paramaribo", "Paramaribo", 
"Paramaribo", "Paramaribo", "Wanica", "Wanica", "Wanica"), Ressort = c("Beekhuizen", 
"Beekhuizen", "Centrum", "Beekhuizen", "Welgelegen", "Nieuwe Grond", 
"Domburg", "Domburg"), Coordinaten = c("5°30'29,88NB, 55°10'44,04WL", 
"5°30'29,88NB, 55°10'44,04WL", "5°30'29,9NB, 55°10'44,0WL", 
"5°30'29,88NB, 55°10'44,04WL", "5°50'33NB, 55°13'7WL", "5°45'NB, 55°13'WL", 
"5°42'NB, 55°5'WL", "5°42'NB, 55°5'WL"), Schoolcode = c("A1", 
"A2", "A3", "A4", "A5", "A6", "A7", "A8")), class = "data.frame", row.names = c(NA, 
-8L))