# ===================================================================================================================== # EThekwini Ward Maps Andrew Collier (andrew@exegetic.biz) # Exegetic Analytics / www.exegetic.biz / info@exegetic.biz / @exegeticdata # ===================================================================================================================== # https://edge.durban/dataset/ethekwini-ward-maps library(sf) library(ggplot2) library(ggmap) library(dplyr) library(readr) library(readxl) library(janitor) # DOWNLOAD KML -------------------------------------------------------------------------------------------------------- KMLFILE = "eth.kml" URL = "http://edge.durban/dataset/64ae3b1f-4ce9-48a3-8136-8c74a139de0f/resource/b6336b5c-49af-4b3a-89fe-e72c1db3a3ea/download/" # URL = file.path(URL, KMLFILE) download.file(URL, KMLFILE) # LOAD DATA ----------------------------------------------------------------------------------------------------------- # Use ogrinfo to find out the name of the layer. # # $ ogrinfo eth.kml # INFO: Open of `eth.kml' # using driver `LIBKML' successful. # 1: ETH wards <- st_read(KMLFILE) # How many records? # nrow(wards) # # Is this the number of wards in Ethekwini? st_geometry(wards) %>% head() st_geometry(wards) %>% tail() # # Aha! There are two types of data: POINT (centroid) and MULTIPOLYGON (boundary). # Let's keep only the polygons. # wards <- st_collection_extract(wards, "POLYGON") # nrow(wards) # QUICK MAPS ---------------------------------------------------------------------------------------------------------- # Draw the ward outlines. # ggplot(wards) + geom_sf() # Add labels. # ggplot(wards) + geom_sf() + geom_sf_label(aes(label = Name)) # BETTER MAPS --------------------------------------------------------------------------------------------------------- # Get bounding box. # bbox <- st_bbox(wards) # names(bbox) # # These names differ from what's required by get_stamenmap(), so remove. # bbox <- unname(bbox) # # Expand the bounding box. # bbox <- bbox + c(-1, -1, +1, +1) / 16 map <- get_stamenmap(bbox, zoom = 10) # Plot map. # ggmap(map) # Plot map and overlay ward boundaries. # ggmap(map) + geom_sf(data = wards, alpha = 0, col = "#3498db", inherit.aes = FALSE) # LOAD SKILLS DATA ---------------------------------------------------------------------------------------------------- XLSXFILE = "ethekwini-skills-development-per-ward.xls" URL = "https://edge.durban/dataset/c5ea99ec-ba22-4b37-973d-9dc30de26d03/resource/1463ecd0-e742-42df-8665-b9c9307d2770/download/" # URL = file.path(URL, XLSXFILE) download.file(URL, XLSXFILE) skills <- read_excel(XLSXFILE) %>% clean_names() # PREPARE SKILLS DATA ------------------------------------------------------------------------------------------------- skills <- skills %>% mutate( drivers_licence = ifelse(drivers_licence == "NOT SPECIFIED", NA, drivers_licence), drivers_licence = factor(drivers_licence), ward_no = as.integer(ward_no), ward_no = ifelse(between(ward_no, 1, 110), ward_no, NA), ward_no = factor(ward_no, levels = 1:110) ) skills_summary <- skills %>% group_by(ward_no) %>% summarise( drivers_licence_fraction = mean(drivers_licence == "YES", na.rm = TRUE), age_mean = mean(age, na.rm = TRUE) ) wards_augmented <- inner_join(wards, skills_summary, by = c("Name" = "ward_no")) ggmap(map) + geom_sf( data = wards_augmented, aes(fill = drivers_licence_fraction), col = "black", alpha = 0.8, inherit.aes = FALSE ) + scale_fill_gradient("% Driver License", limits = c(0, 1), low = "white", high = "#3498db") + labs(x = NULL, y = NULL) ggsave("drivers-license-spatial.png", width = 6, height = 6, dpi = 150) # OTHER DATA ---------------------------------------------------------------------------------------------------------- # gis.durban.gov.za/DataDownloads/showdocs.asp # datafirst.uct.ac.za # scoda.co.za # odza.opendata.durban