Railways
R-bloggers 2025-12-06
[This article was first published on r.iresmi.net, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Day 25–26 of 30DayMapChallenge: « Hexagons » and « Transports » (previously).
Estimating the disappearance of railway lines in France.
Config
library(sf)library(glue)library(ggplot2)library(janitor)library(ggspatial)library(dplyr)library(tidyr)library(units)library(osmdata)
Data
# Get and cache OSM data for abandoned railways in Franceif (!file.exists("lost_railways.gpkg")) { railways <- r"([out:xml][timeout:6000]; // Get France as area area["name"="France"]->.fr; ( // Direct generic railway status tags way["railway"~"^(disused|abandoned|razed|dismantled|demolished|retired)$"](area.fr); // Include specific rail / tram / light_rail... in same statuses way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["disused"="yes"](area.fr); way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["abandoned"="yes"](area.fr); way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["razed"="yes"](area.fr); way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["dismantled"="yes"](area.fr); way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["demolished"="yes"](area.fr); way["railway"~"^(rail|tram|light_rail|narrow_gauge)$"]["retired"="yes"](area.fr); // Lifecycle prefix tags for some railway subtype // Matches patterns like: disused:railway=rail, abandoned:railway=tram, etc. way[~"^(disused|abandoned|razed|dismantled|demolished|retired):railway$"~"^(rail|tram|light_rail|narrow_gauge)$"](area.fr); ); (._;>;); out body;)" |> osmdata_sf() lost_railways <- railways$osm_lines |> clean_names() |> select(railway, name) |> write_sf("lost_railways.gpkg")} else { lost_railways <- read_sf("lost_railways.gpkg")}# Hexagonal grid# See https://r.iresmi.net/posts/2024/discrete_global_grid/hex_size <- 20 # kmhex <- read_sf("../../2024/discrete_global_grid/dggrid_fx.gpkg", layer = glue("dggrid_{hex_size}k")) |> st_transform("EPSG:2154")dep <- "~/data/adminexpress/adminexpress_cog_simpl_000_2022.gpkg" |> read_sf(layer = "departement_int")We intersect the railways tracks with the hexagonal grid and calculate the total length per cell.
railways_length <- lost_railways |> st_transform("EPSG:2154") |> st_intersection(hex) |> mutate(length = st_length(geom)) |> st_drop_geometry() |> group_by(seqnum) |> summarise(length = drop_units(set_units(sum(length), km)))Map
hex |> left_join(railways_length, join_by(seqnum)) |> replace_na(list(length = 0)) |> ggplot() + geom_sf(aes(fill = length, color = length)) + geom_sf(data = dep, fill = NA, color = "lightgrey", linewidth = 0.3, alpha = 0.8) + scale_fill_viridis_c(name = "former railways length\nper cell (km)", trans = "sqrt", aesthetics = c("fill", "color")) + annotation_scale(height = unit(1, "mm"), text_col = "darkgrey", line_col = "grey", bar_cols = c("white", "grey")) + labs(title = "The vanished railways", subtitle = glue("Currently disused, abandoned, dismantled... \\ railways in France"), caption = glue("data: OpenStreetMap contributors départements based on IGN AdminExpress 2022 Discrete Global Grid ISEA3H ≈ {hex_size} km, one hexagon ≈ {round(hex_size^2 * sqrt(3) / 2)} km² https://r.iresmi.net - {Sys.Date()}")) + theme_void() + theme(plot.caption = element_text(size = 7, color = "grey40"), plot.margin = unit(c(.2, .2, .2, .2), units = "cm"), legend.position = "bottom")

To leave a comment for the author, please follow the link and comment on their blog: r.iresmi.net.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
