class: center, middle, inverse, title-slide .title[ # Jittering and routing options for converting origin-destination data into route networks ] .subtitle[ ## Towards accurate estimates of movement at the street level ] .author[ ### Robin Lovelace, University of Leeds
+
Rosa Félix
,
Dustin Carlino
] .date[ ###
FOSS4G 2022
] --- --- # Background - We need to build dense walking/cycling/wheeling networks - But where?  Source: Cycle Routing Uptake and Scenario Estimation (CRUSE) tool --- # Tools of the trade <img src="https://docs.ropensci.org/stplanr/reference/figures/stplanr.png" width="30%" /><img src="https://raw.githubusercontent.com/ropensci/stats19/master/man/figures/logo.png" width="30%" /><img src="https://github.com/Robinlovelace/geocompr/blob/main/images/geocompr_hex.png?raw=true" width="30%" /> --  ??? - Need for more sustainable transport systems - Local authorities need data - We've developed a number of tools that provide this data --- ### Modelling framework and long-standing limitations .left-column[ Modular Future proof Scalable Vector/  Raster/  Source: Morgan and Lovelace ([2020](https://doi.org/10.1177/2399808320942779 )) Implementation: [stplanr](https://docs.ropensci.org/stplanr/index.html) ] -- .right-column[ <!-- --> Approach: OD -> Desire Line -> Route -> Route Networks ] --- ## What is Jittering?  Source: Lovelace, R., Félix, R., & Carlino, D. (2022, January 13). Jittering: A computationally efficient method for generating realistic route networks from origin-destination data. Transport Findings, in Press https://doi.org/10.31219/osf.io/qux6g --- ## Current default: centroid-based desire lines (+routes+rnets)  --- ## Jittering in action: minimal reproducible example  --- ### Jittering a larger dataset Adding value and detail to existing OD data. Source: Lovelace, Félix and Carlino ([2022](https://osf.io/qux6g/))  --- ## Resulting route network  --- ### Validating the approach: MKI Data from Edinburgh. Source: [GISRUK 2022 conference paper](https://zenodo.org/record/6410196). -- .pull-left[  See slides [here](https://www.robinlovelace.net/presentations/gisruk2022-jittering.html#1 ) ] .pull-right[ <blockquote class="twitter-tweet"><p lang="en" dir="ltr">Just presented new 'jittering' approach to pre-processing origin-destination (OD) data by diversifying simulated O/D locations <a href="https://twitter.com/GISRUK?ref_src=twsrc%5Etfw">@GISRUK</a>🎉<br><br>Great to get these new methods + reproducible implementation in open source software (<a href="https://twitter.com/rustlang?ref_src=twsrc%5Etfw">@rustlang</a> + <a href="https://twitter.com/hashtag/RStats?src=hash&ref_src=twsrc%5Etfw">#RStats</a> + ...) out there, give them a spin! <a href="https://t.co/vaydCHajm8">pic.twitter.com/vaydCHajm8</a></p>— Robin Lovelace (@robinlovelace) <a href="https://twitter.com/robinlovelace/status/1511739257962045440?ref_src=twsrc%5Etfw">April 6, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> ] --- ### Model experiments: jittering parameters  --- ## Results From Edinburgh  --- # Changing jittering *and* routing params #### The 'jittering only' approach is assumes perfect routing, not true #### Model/data discrepancies may be more due to routing than jittering/OD parameters Enter Lisbon!  --- # Network level results  --- # Summary of results  --- #### Next steps Exploring the parameter space: different origin and destination points + weights, routing 'engines', disaggregation. .pull-left[ #### Selection of input data: open options - Traffic count data - Urban Observatory type data (Newcastle, Birmingham, Manchester) - Faceboook and Google open mobility data - 'OSM2od' - spatial interaction model - Modelled data - jittering: spatial disaggregation - temporal disaggregation ] .pull-right[ #### Non-open data data - National Travel Survey - Mobile Telephone Data - Large GPS type data (biobank, Google timeline, Straval) ] --- ## Appendix: Reproducible code I: Rust implementation See reproducible repo + manuscript here: https://github.com/Robinlovelace/odnet System command line implementation (compile Rust code): ```bash cargo install --git https://github.com/dabreegster/odjitter odjitter jitter --od-csv-path od_iz_ed.csv \ --zones-path iz_zones11_ed.geojson \ --subpoints-path road_network_ed.geojson \ --max-per-od 10 --output-path output_max50.geojson ``` --- # Reproducible code II: R implementation (See code in slides.Rmd in robinlovelace/foss4g22 for code to get data) ```r remotes::install_github("dabreegster/odjitter", subdir = "r") ``` ```r od = read_csv("od_iz_ed.csv") zones = sf::read_sf("iz_zones11_ed.geojson") ``` ```r od_jittered = odjitter::jitter( od = od, zones = zones, subpoints = sf::read_sf("road_network_ed.geojson") ) od_jittered2 = odjitter::jitter( od = od, zones = zones, subpoints = sf::read_sf("road_network_ed.geojson"), disaggregation_key = "all", disaggregation_threshold = 10 ) ``` --- ### Results of reprex 1 ```r od_sf = od::od_to_sf( od, zones ) nrow(od_sf) ``` ``` ## [1] 10394 ``` ```r nrow(od_jittered) ``` ``` ## [1] 10394 ``` ```r nrow(od_jittered2) ``` ``` ## [1] 22432 ``` --- # Plot of unjittered data ```r library(dplyr) plot(od_sf$geometry, lwd = od_sf$all / 500) ``` <!-- --> --- ### Results of reprex 2 ```r plot(od_jittered$geometry, lwd = od_jittered$all / 500) ``` <!-- --> --- ### Results of reprex 3 ```r plot(od_jittered2$geometry, lwd = od_jittered2$all / 50) ``` <!-- --> --- ### Alternative validation datasets: OA-WPZ data There are 17,848,366 OA to WPZ records, 170k OAs, 54k WPZ For 5km buffer around London, 1.5 million OD pairs with destinations [](https://rpubs.com/RobinLovelace/863109) --- ### Reproducible example .left-column[ ```r u = "https://github.com/ITSLeeds/od/releases/download/v0.3.1/od_intra_top_sf.geojson" desire_lines_oa_wpz_1k = sf::read_sf(u) oas_in_buffer = sf::read_sf("https://github.com/ITSLeeds/od/releases/download/v0.3.1/oas_in_buffer.geojson") wpz_in_buffer = sf::read_sf("https://github.com/ITSLeeds/od/releases/download/v0.3.1/wpz_in_buffer.geojson") library(tmap) tmap_mode("view") ``` ``` ## tmap mode set to interactive viewing ``` ```r m = tm_shape(desire_lines_oa_wpz_1k) + tm_lines() + tm_shape(oas_in_buffer) + tm_dots(col = "darkgreen") + tm_shape(wpz_in_buffer) + tm_dots(col = "darkred") ``` ] .right-column[ See [here](https://rpubs.com/anon-user/887139) for map  ]