Skip to content

Instantly share code, notes, and snippets.

@mschnetzer
Last active December 2, 2022 22:23
Show Gist options
  • Save mschnetzer/3c9e1fe4e0c5f04123033d9d689e75b9 to your computer and use it in GitHub Desktop.
Save mschnetzer/3c9e1fe4e0c5f04123033d9d689e75b9 to your computer and use it in GitHub Desktop.
Vienna's buildings by construction periods (https://twitter.com/matschnetzer/status/1598586751190278146)
librarian::shelf(tidyverse, sf, ows4R, httr, msthemes, osmdata, RColorBrewer, ggtext, showtext)
# Add Google fonts
font_add_google(name = "Bodoni Moda", family = "bodoni")
font_add_google(name = "Roboto Slab", family = "roboto-slab")
font_add_google(name = "Roboto Slab", family = "roboto-slab-thin", regular.wt = 300, bold.wt = 500)
showtext_auto()
# Define map boundaries
bb <- c(16.3151, 48.1856, 16.4087, 48.2279)
stephansdom <- c(16.37317, 48.20852)
# OSM background (streets, rivers, buildings)
wienbg <- opq(bbox = bb) |>
add_osm_feature(key = 'highway', value = c("primary","secondary","tertiary")) |>
osmdata_sf()
wienbgsf <- wienbg$osm_lines |> st_transform(crs = 4326)
wienwater <- opq(bbox = bb) |>
add_osm_feature(key = 'natural', value = "water") |>
osmdata_sf()
wienwatersf <- wienwater$osm_multipolygons |> st_transform(crs = 4326)
wienbuild <- opq(bbox = bb) |>
add_osm_feature(key = 'building') |>
osmdata_sf()
wienbuildsf <- wienbuild$osm_polygons |> st_transform(crs = 4326)
# Create circle shape with a 2km radius
circle <- tibble(lat = stephansdom[1], long = stephansdom[2]) |>
st_as_sf(coords = c("lat", "long"), crs = 4326) |>
st_transform(crs = 6384) |> st_buffer(dist = 2000) |> st_transform(crs = 4326)
# Map data from WFS (Stadt Wien)
wfs_wien <- "https://data.wien.gv.at/daten/geo"
wien_client <- WFSClient$new(wfs_wien, serviceVersion = "1.0.0")
wien_client$getFeatureTypes(pretty = TRUE)
url <- parse_url(wfs_wien)
url$query <- list(service = "WFS",
version = "1.1.0",
request = "GetFeature",
typeName = "ogdwien:BAUPERIODEDETAILOGD",
SRS = "EPSG:4326",
BBOX = paste0(paste0(bb,collapse=","),",EPSG:4326"))
request <- build_url(url)
wien_map <- read_sf(request) |> st_set_crs(31256) |> st_transform(crs = 4326)
# Edit messy data and fix construction periods
wien_map <- wien_map |>
mutate(periode = case_when(
OBJ_STR2_TXT == "vor 1848" ~ "1781-1848",
OBJ_STR2_TXT == "1848 -1918" ~ "1884-1918",
OBJ_STR2_TXT == "1884-1918" ~ "1884-1918",
OBJ_STR2_TXT == "1919 - 1945" ~ "1919-1945",
OBJ_STR2_TXT == "nach 1945" ~ "1946-1976",
OBJ_STR_TXT == "Keine Angabe" ~ NA_character_,
OBJ_STR_TXT == "Vor 1848" ~ "1781-1848",
OBJ_STR_TXT == "Vor 1683" ~ "before 1683",
OBJ_STR_TXT == "Nach 1976" ~ "after 1976",
OBJ_STR_TXT == "1848-1918" ~ "1884-1918", # data coding error
TRUE ~ OBJ_STR_TXT),
periode = factor(periode, levels = c("before 1683","1683-1740","1741-1780","1781-1848","1849-1859","1860-1883","1884-1918","1919-1945","1946-1976","after 1976")))
# Cropping data with circle
street_crop <- wienbgsf |> st_intersection(circle)
water_crop <- wienwatersf |> st_intersection(circle)
base_crop <- wienbuildsf |> st_intersection(circle)
wien_crop <- wien_map |>
filter(st_geometry_type(SHAPE) %in% c("POLYGON","MULTIPOLYGON")) |>
st_intersection(circle)
# Final clean-up in the data
# Get rid of duplicates, keep observation with highest frequency of building period
wien_crop <- wien_crop |> filter(!is.na(periode)) |>
group_by(OBJECTID) |> add_count(periode) |>
group_by(OBJECTID) |> slice_max(n, n=1, with_ties = F)
# Draw plot
wienplot <- ggplot() +
geom_sf(data = base_crop, fill = "gray20", size = NA, color = NA, alpha = 0.7) +
geom_sf(data = water_crop, fill = "lightblue", size = 0.2) +
geom_sf(data = street_crop, color = "gray85", size = 0.2, alpha = 0.8) +
geom_sf(data = wien_crop |> filter(!is.na(periode)), aes(fill = periode), color = NA) +
scale_fill_manual(name = "Year of construction",
values = colorRampPalette(brewer.pal(11, "Spectral"))(10),
guide = guide_legend(keywidth = unit(0.3,"lines"), title.position = "left", title.hjust = 0)) +
labs(title = "Vienna", caption = "Source: Stadt Wien, OpenStreetMaps. Figure: @matschnetzer",
subtitle = "This map shows the city center of the Austrian capital by construction periods. Parts of the center were built even<br><b style='color:#9E0142'>before the Battle of Vienna in 1683</b> after the imperial city had been besieged by the Ottoman Empire for two months.<br>Many important buildings of the Ringstraße were constructed in the <b style='color:#F1F9A9'>'Gründerzeit' era between 1860 and 1883</b>.<br>Only a few buildings in the inner city were built <b style='color:#5E4FA2'>after 1976</b>.") +
theme_ms(grid = F, dark = T, alttf = T) +
theme(axis.text = element_blank(),
plot.title = element_text(hjust = 0.5, size = 110, family = "bodoni", margin = margin(b = 0.3, unit = "cm")),
plot.subtitle = element_markdown(size = 25, family = "roboto-slab-thin", lineheight=0.4),
plot.caption = element_text(size = 20, family = "roboto-slab", hjust = 1),
plot.caption.position = "plot",
legend.title = element_text(size = 25, family = "roboto-slab", angle = 90, margin = margin(r=-5, unit = "pt")),
legend.text = element_text(size = 25, family = "roboto-slab"),
plot.background = element_rect(fill="black"))
ggsave(wienplot, filename = "wienplot.png", dpi = 320, width = 7, height = 6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment