Visualising Urban Geographies was a project by Edinburgh University that iprovided an amazing collection of geo-referenced maps, geographic boundaries and socio econoic maps - Project Website. Here I use some of them to create a vizualizations in R.

Packages

library(sf)
library(ggplot2)
library(gganimate)
library(ggpomological)
library(magick)
library(dplyr)
library(readr)
library(ggmap)

Chronological Map

Chronological Map of Edinburgh Showing the Expansion of the City 1919 created by John George Bartholomew.

Data

First we are going to load the data.

# load the shp
chrono_map = st_read("data/spatial/bart_chrono_1919.shp", quiet = TRUE)

#period colors
period_colors = c("#851613","#C83B42","#DE7B80","#F0AEB1",
                  "#135D89","#4D95BA","#96D1EA","#52442F","#BEB3A1","#F0E7D9")
#period labels
period_labels = c("pre 1450","1450 - 1515","1515 - 1622","1622 - 1750",
                  "1750 - 1800 ","1800 - 1825","1825 - 1850","1850 - 1875",
                  "1875 - 1900","since 1900")

Animation

Now, we can create the animated map

#plot map for animation
map = ggplot() + 
  geom_sf(
    data = chrono_map,
    aes(fill= as.factor(End_Date)),
    alpha = 0.75, 
    colour = NA) +
  scale_fill_manual(name = "End of {current_frame}", values = period_colors, labels = period_labels) +
  theme_pomological() +
  labs(
    title = "Chronological Map of Edinburgh",
    subtitle = "Showing expansion of the City from earliest days to the present \nby J.G. Bartholomew - Cartographer to the King",
    caption = "https://geo.nls.uk/urbhist/"
  ) +
  transition_manual(End_Date, cumulative = T)

# plot static map
map = ggplot() + 
  geom_sf(
    data = chrono_map,
    aes(fill= as.factor(End_Date)),
    alpha = 0.75, 
    colour = NA) +
  scale_fill_manual(name = "period ", values = period_colors, labels = period_labels,
                    guide = guide_legend(
                      direction = 'horizontal',
                      title.position = 'top',
                      title.hjust = .5,
                      label.position = 'bottom',
                      label.hjust = .5,
                      keywidth = .5,
                      keyheight = .5,
                      nrow = 1
                    ))+
  labs(
    title = "Chronological Map of Edinburgh",
    subtitle = "Showing expansion of the City from earliest days to the present \nby J.G. Bartholomew - Cartographer to the King",
    caption = "Source: https://geo.nls.uk/urbhist/"
  ) +
  theme_pomological() +
  theme(
    legend.position = "bottom"
  ) +
  transition_manual(End_Date, cumulative = T)

#create animation
animate(map, width = 800, height = 600)

#save gif
anim_save("map_anim.gif", map, width = 800,height = 600)

Occupations

Here we will map a selection of Edinburgh professions in 1911.

occupations_edi = read_csv("data/processed/occupations.csv")

base_plot = qmplot(
  data = occupations_edi,
  x = long,
  y = lat,
  zoom = 14,
  geom = "blank",
  maptype = "toner-lines",
  source = 'stamen'
)

base_plot +
  geom_point(mapping = aes(x = long, y = lat), size = .5) +
  labs(
    title = "Edinburgh Occupations in 1911",
    caption = "Source: vug | @topographos2"
  ) +
  theme_pomological(
  ) +
  theme(
    axis.title.x=element_blank(),
    axis.title.y=element_blank()
  ) +
  facet_wrap(~ occupation)

Short and sweet !

sessionInfo()
## R version 4.0.2 (2020-06-22)
## Platform: x86_64-apple-darwin17.0 (64-bit)
## Running under: macOS Mojave 10.14.6
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRblas.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
## 
## locale:
## [1] en_GB.UTF-8/en_GB.UTF-8/en_GB.UTF-8/C/en_GB.UTF-8/en_GB.UTF-8
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] ggmap_3.0.0.902     readr_1.4.0         dplyr_1.0.2        
## [4] magick_2.3          ggpomological_0.1.2 gganimate_1.0.5    
## [7] ggplot2_3.3.2       sf_0.9-6           
## 
## loaded via a namespace (and not attached):
##  [1] progress_1.2.2      tidyselect_1.1.0    xfun_0.22          
##  [4] purrr_0.3.4         lattice_0.20-41     colorspace_1.4-1   
##  [7] vctrs_0.3.6         generics_0.1.0      htmltools_0.5.1.1  
## [10] yaml_2.2.1          rlang_0.4.10        e1071_1.7-4        
## [13] pillar_1.4.7        glue_1.4.2          withr_2.3.0        
## [16] DBI_1.1.0           tweenr_1.0.1        sp_1.4-5           
## [19] jpeg_0.1-8.1        lifecycle_0.2.0     plyr_1.8.6         
## [22] stringr_1.4.0.9000  munsell_0.5.0       gtable_0.3.0       
## [25] RgoogleMaps_1.4.5.3 evaluate_0.14       labeling_0.4.2     
## [28] knitr_1.31          curl_4.3            class_7.3-17       
## [31] gifski_0.8.6        highr_0.8           Rcpp_1.0.6         
## [34] KernSmooth_2.23-17  scales_1.1.1        classInt_0.4-3     
## [37] farver_2.0.3        rjson_0.2.20        hms_0.5.3          
## [40] png_0.1-7           digest_0.6.27       stringi_1.5.3      
## [43] grid_4.0.2          cli_2.3.1           tools_4.0.2        
## [46] bitops_1.0-6        magrittr_2.0.1      tibble_3.0.4       
## [49] tidyr_1.1.2         crayon_1.4.1        pkgconfig_2.0.3    
## [52] ellipsis_0.3.1      prettyunits_1.1.1   rstudioapi_0.13    
## [55] assertthat_0.2.1    rmarkdown_2.6.4     httr_1.4.2         
## [58] R6_2.5.0            units_0.6-7         compiler_4.0.2
 

A work by Michal Michalski

LS0tCnRpdGxlOiAiVlVHIGluIFIiCmF1dGhvcjogIk1pY2hhbCBNaWNoYWxza2kiCmRhdGU6ICIyOS8wNS8yMDIwIgpvdXRwdXQ6IAogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRoZW1lOiBmbGF0bHkKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiAKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlCiAgCi0tLQo8c3R5bGU+CmRpdi5ibHVlIHsgYmFja2dyb3VuZC1jb2xvcjojRDNEM0QzOyBib3JkZXItcmFkaXVzOiA1cHg7IHBhZGRpbmc6IDIwcHg7fQo8L3N0eWxlPgo8ZGl2IGNsYXNzID0gImJsdWUiPgpWaXN1YWxpc2luZyBVcmJhbiBHZW9ncmFwaGllcyB3YXMgYSBwcm9qZWN0IGJ5IEVkaW5idXJnaCBVbml2ZXJzaXR5IHRoYXQgaXByb3ZpZGVkIGFuIGFtYXppbmcgY29sbGVjdGlvbiBvZiBnZW8tcmVmZXJlbmNlZCBtYXBzLCBnZW9ncmFwaGljIGJvdW5kYXJpZXMgYW5kIHNvY2lvIGVjb25vaWMgbWFwcyAtIFtQcm9qZWN0IFdlYnNpdGVdKGh0dHBzOi8vZ2VvLm5scy51ay91cmJoaXN0LykuCkhlcmUgSSB1c2Ugc29tZSBvZiB0aGVtIHRvIGNyZWF0ZSBhIHZpenVhbGl6YXRpb25zIGluIFIuCjwvZGl2PgoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKIyMgUGFja2FnZXMKCmBgYHtyIHBhY2thZ2VzLCBlY2hvPVRSVUUsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIHBhZ2VkLnByaW50PUZBTFNFfQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dhbmltYXRlKQpsaWJyYXJ5KGdncG9tb2xvZ2ljYWwpCmxpYnJhcnkobWFnaWNrKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGdnbWFwKQoKYGBgCgojIyBDaHJvbm9sb2dpY2FsIE1hcAoKQ2hyb25vbG9naWNhbCBNYXAgb2YgRWRpbmJ1cmdoIFNob3dpbmcgdGhlIEV4cGFuc2lvbiBvZiB0aGUgQ2l0eSAxOTE5IGNyZWF0ZWQgYnkgSm9obiBHZW9yZ2UgQmFydGhvbG9tZXcuCgojIyMgRGF0YQoKRmlyc3Qgd2UgYXJlIGdvaW5nIHRvIGxvYWQgdGhlIGRhdGEuCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBwYWdlZC5wcmludD1GQUxTRX0KIyBsb2FkIHRoZSBzaHAKY2hyb25vX21hcCA9IHN0X3JlYWQoImRhdGEvc3BhdGlhbC9iYXJ0X2Nocm9ub18xOTE5LnNocCIsIHF1aWV0ID0gVFJVRSkKCiNwZXJpb2QgY29sb3JzCnBlcmlvZF9jb2xvcnMgPSBjKCIjODUxNjEzIiwiI0M4M0I0MiIsIiNERTdCODAiLCIjRjBBRUIxIiwKICAgICAgICAgICAgICAgICAgIiMxMzVEODkiLCIjNEQ5NUJBIiwiIzk2RDFFQSIsIiM1MjQ0MkYiLCIjQkVCM0ExIiwiI0YwRTdEOSIpCiNwZXJpb2QgbGFiZWxzCnBlcmlvZF9sYWJlbHMgPSBjKCJwcmUgMTQ1MCIsIjE0NTAgLSAxNTE1IiwiMTUxNSAtIDE2MjIiLCIxNjIyIC0gMTc1MCIsCiAgICAgICAgICAgICAgICAgICIxNzUwIC0gMTgwMCAiLCIxODAwIC0gMTgyNSIsIjE4MjUgLSAxODUwIiwiMTg1MCAtIDE4NzUiLAogICAgICAgICAgICAgICAgICAiMTg3NSAtIDE5MDAiLCJzaW5jZSAxOTAwIikKYGBgCgojIyMgQW5pbWF0aW9uCgpOb3csIHdlIGNhbiBjcmVhdGUgdGhlIGFuaW1hdGVkIG1hcAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9CgojcGxvdCBtYXAgZm9yIGFuaW1hdGlvbgptYXAgPSBnZ3Bsb3QoKSArIAogIGdlb21fc2YoCiAgICBkYXRhID0gY2hyb25vX21hcCwKICAgIGFlcyhmaWxsPSBhcy5mYWN0b3IoRW5kX0RhdGUpKSwKICAgIGFscGhhID0gMC43NSwgCiAgICBjb2xvdXIgPSBOQSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiRW5kIG9mIHtjdXJyZW50X2ZyYW1lfSIsIHZhbHVlcyA9IHBlcmlvZF9jb2xvcnMsIGxhYmVscyA9IHBlcmlvZF9sYWJlbHMpICsKICB0aGVtZV9wb21vbG9naWNhbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQ2hyb25vbG9naWNhbCBNYXAgb2YgRWRpbmJ1cmdoIiwKICAgIHN1YnRpdGxlID0gIlNob3dpbmcgZXhwYW5zaW9uIG9mIHRoZSBDaXR5IGZyb20gZWFybGllc3QgZGF5cyB0byB0aGUgcHJlc2VudCBcbmJ5IEouRy4gQmFydGhvbG9tZXcgLSBDYXJ0b2dyYXBoZXIgdG8gdGhlIEtpbmciLAogICAgY2FwdGlvbiA9ICJodHRwczovL2dlby5ubHMudWsvdXJiaGlzdC8iCiAgKSArCiAgdHJhbnNpdGlvbl9tYW51YWwoRW5kX0RhdGUsIGN1bXVsYXRpdmUgPSBUKQoKIyBwbG90IHN0YXRpYyBtYXAKbWFwID0gZ2dwbG90KCkgKyAKICBnZW9tX3NmKAogICAgZGF0YSA9IGNocm9ub19tYXAsCiAgICBhZXMoZmlsbD0gYXMuZmFjdG9yKEVuZF9EYXRlKSksCiAgICBhbHBoYSA9IDAuNzUsIAogICAgY29sb3VyID0gTkEpICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gInBlcmlvZCAiLCB2YWx1ZXMgPSBwZXJpb2RfY29sb3JzLCBsYWJlbHMgPSBwZXJpb2RfbGFiZWxzLAogICAgICAgICAgICAgICAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gJ2hvcml6b250YWwnLAogICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAndG9wJywKICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmhqdXN0ID0gLjUsCiAgICAgICAgICAgICAgICAgICAgICBsYWJlbC5wb3NpdGlvbiA9ICdib3R0b20nLAogICAgICAgICAgICAgICAgICAgICAgbGFiZWwuaGp1c3QgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgIGtleXdpZHRoID0gLjUsCiAgICAgICAgICAgICAgICAgICAgICBrZXloZWlnaHQgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSAxCiAgICAgICAgICAgICAgICAgICAgKSkrCiAgbGFicygKICAgIHRpdGxlID0gIkNocm9ub2xvZ2ljYWwgTWFwIG9mIEVkaW5idXJnaCIsCiAgICBzdWJ0aXRsZSA9ICJTaG93aW5nIGV4cGFuc2lvbiBvZiB0aGUgQ2l0eSBmcm9tIGVhcmxpZXN0IGRheXMgdG8gdGhlIHByZXNlbnQgXG5ieSBKLkcuIEJhcnRob2xvbWV3IC0gQ2FydG9ncmFwaGVyIHRvIHRoZSBLaW5nIiwKICAgIGNhcHRpb24gPSAiU291cmNlOiBodHRwczovL2dlby5ubHMudWsvdXJiaGlzdC8iCiAgKSArCiAgdGhlbWVfcG9tb2xvZ2ljYWwoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIgogICkgKwogIHRyYW5zaXRpb25fbWFudWFsKEVuZF9EYXRlLCBjdW11bGF0aXZlID0gVCkKCiNjcmVhdGUgYW5pbWF0aW9uCmFuaW1hdGUobWFwLCB3aWR0aCA9IDgwMCwgaGVpZ2h0ID0gNjAwKQoKI3NhdmUgZ2lmCmFuaW1fc2F2ZSgibWFwX2FuaW0uZ2lmIiwgbWFwLCB3aWR0aCA9IDgwMCxoZWlnaHQgPSA2MDApCgpgYGAKCiMjIE9jY3VwYXRpb25zCgpIZXJlIHdlIHdpbGwgbWFwIGEgc2VsZWN0aW9uIG9mIEVkaW5idXJnaCBwcm9mZXNzaW9ucyBpbiAxOTExLgoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgcGFnZWQucHJpbnQ9RkFMU0V9Cm9jY3VwYXRpb25zX2VkaSA9IHJlYWRfY3N2KCJkYXRhL3Byb2Nlc3NlZC9vY2N1cGF0aW9ucy5jc3YiKQoKYmFzZV9wbG90ID0gcW1wbG90KAogIGRhdGEgPSBvY2N1cGF0aW9uc19lZGksCiAgeCA9IGxvbmcsCiAgeSA9IGxhdCwKICB6b29tID0gMTQsCiAgZ2VvbSA9ICJibGFuayIsCiAgbWFwdHlwZSA9ICJ0b25lci1saW5lcyIsCiAgc291cmNlID0gJ3N0YW1lbicKKQoKYmFzZV9wbG90ICsKICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IGxvbmcsIHkgPSBsYXQpLCBzaXplID0gLjUpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRWRpbmJ1cmdoIE9jY3VwYXRpb25zIGluIDE5MTEiLAogICAgY2FwdGlvbiA9ICJTb3VyY2U6IHZ1ZyB8IEB0b3BvZ3JhcGhvczIiCiAgKSArCiAgdGhlbWVfcG9tb2xvZ2ljYWwoCiAgKSArCiAgdGhlbWUoCiAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKQogICkgKwogIGZhY2V0X3dyYXAofiBvY2N1cGF0aW9uKQpgYGAKClNob3J0IGFuZCBzd2VldCAhCgpgYGB7cn0Kc2Vzc2lvbkluZm8oKQpgYGAKCgombmJzcDsKPGhyIC8+CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij5BIHdvcmsgYnkgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL3RvcG9ncmFwaG9zLyI+TWljaGFsIE1pY2hhbHNraTwvYT48L3A+CjxwIHN0eWxlPSJ0ZXh0LWFsaWduOiBjZW50ZXI7Ij48c3BhbiBzdHlsZT0iY29sb3I6ICM4MDgwODA7Ij4K