
Gonçalo F. Matos, Rosa Félix, Filipe Moura

🚌💨 Eficcient public transport
🚗🚫 Reduce car dependency
🤝🍃 Equitable and sustainable mobility
🚌💨 Eficcient public transport
🚗🚫 Reduce car dependency
🤝🍃 Equitable and sustainable mobility
🚗👎 Congestion hampers bus services
⌛💸 Costs for users and operations
🏙️👀 Urban space is limited
🏙️👀 Urban space is limited
Interventions must be underlied on reliable and robust information

Gonçalo F. Matos, Rosa Félix, Filipe Moura





Used in travel planning apps


relation[route=bus]
relation[route=bus]



… associating GTFS and OSM data requires conflation
Combination of “geographic information from overlapping sources so as to retain accurate data, minimize redundancy, and reconcile data conflict” (Longley et al. 2001)
👀 Some authors have proposed methods to combine them by using routing algorithms (Hubsch 2026; Gabriele 2026; Poletti 2016; Bast and Brosi 2018)
🔎 However, they ignore the database of already existing OSM route relations, being computational demanding and more prone to errors
R package focused on harmonising GTFS and OSM data to enable integrated public transport modeling
Public transport operations 
![]()
OSM road network 
GTFShift
GTFShift::osm_shapes_match_routes()
Matching of GTFS shapes, \(i\), with OSM relations, \(j\), based on geometrical correspondence using a closeness heuristic
\[C(i, j)\]
that aims to minimize:
GTFShift
GTFShift::osm_shapes_match_routes()
Matching of GTFS shapes, \(i\), with OSM relations, \(j\), based on geometrical correspondence using a closeness heuristic
\[C(i, j) = d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j})\]
that aims to minimize:
GTFShift
GTFShift::osm_shapes_match_routes()
Matching of GTFS shapes, \(i\), with OSM relations, \(j\), based on geometrical correspondence using a closeness heuristic
\[C(i, j) = d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j}) + |L_{GTFS, i} - L_{OSM, j}|\]
that aims to minimize:
distance between departure and arrival stops, \(d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j})\)
length difference, \(|L_{GTFS, i} - L_{OSM, j}|\)
GTFShift
GTFShift::osm_shapes_match_routes()
Matching of GTFS shapes, \(i\), with OSM relations, \(j\), based on geometrical correspondence using a closeness heuristic
\[C(i, j) = d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j}) + |L_{GTFS, i} - L_{OSM, j}| + \frac{L_{GTFS, i}}{N_{stops, i}} \cdot |N_{stops, i} - N_{stops, j}|\]
that aims to minimize:
distance between departure and arrival stops, \(d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j})\)
length difference, \(|L_{GTFS, i} - L_{OSM, j}|\)
number of stops difference, \(\frac{L_{GTFS, i}}{N_{stops, i}} \cdot |N_{stops, i} - N_{stops, j}|\)
GTFShift
GTFShift::osm_shapes_match_routes()
Matching of GTFS shapes, \(i\), with OSM relations, \(j\), based on geometrical correspondence using a closeness heuristic
\[C(i, j) = d(\text{init}_{GTFS, i}, \text{init}_{OSM, j}) + d(\text{fin}_{GTFS, i}, \text{fin}_{OSM, j}) + |L_{GTFS, i} - L_{OSM, j}| + \frac{L_{GTFS, i}}{N_{stops, i}} \cdot |N_{stops, i} - N_{stops, j}|\]
Shape \(S_i\) is associated with the OSM route \(O_{j^*}\) that minimizes its value:
\[j^* = \operatorname{argmin}_{j} C(i, j)\]
Lisbon Metropolitan Area




| Operator | Matched shapes (%) | Matched shapes peak (%) | Matched trips (%) | Matched trips peak (%) |
|---|---|---|---|---|
| Carris | 99.62 | 100 | 99.96 | 100 |
| TCB | 91.66 | 100 | 96.78 | 100 |
| MobiCascais | 94.62 | 96.51 | 97.27 | 96.61 |
| Carris Metropolitana | 98.96 | 99.53 | 99.36 | 99.76 |
High match rate, that increases when considering peak hour (08:00)
| Operator | Heuristic length (m)¹ | Heuristic points (m)¹ | Heuristic stops (n)¹ |
|---|---|---|---|
| Carris | 278.9 ± 1300.6 | 45.4 ± 176.7 | 0.38 ± 0.70 |
| TCB | 146.6 ± 202.4 | 84.0 ± 359.2 | 0.11 ± 0.31 |
| MobiCascais | 130.5 ± 447.8 | 161.1 ± 866.6 | 0.46 ± 1.01 |
| Carris Metropolitana | 314.0 ± 466.5 | 72.65 ± 649.3 | 0.40 ± 0.93 |
Closeness heuristic varies across operators, that reveal:
Poor quality of Carris GTFS shape geometries
MobiCascais route variants not mapped on OSM
Carris GTFS shape geometries improved after OSM match
Before 

Carris GTFS shape geometries improved after OSM match
Before 
After 
Filtering by length difference <1000 m and start/end point distance <500 m
| Operator | Matched shapes after filtering (n) | Matched shapes peak¹ (%) | Matched trips peak¹ (%) |
|---|---|---|---|
| Carris | 251 | 97.16 | 97.49 |
| TCB | 52 | 90.32 | 96.40 |
| MobiCascais | 117 | 91.86 | 94.49 |
| Carris Metropolitana | 1369 | 92.42 | 94.03 |
Match remains >90% for all operators
Going back to the initial example…
Before 

Going back to the initial example…
Before 
After 
GTFShift
GTFShift::osm_shapes_match_routes()
🌐 Open source method that relies on open data
💯 Simple and effective method to improve GTFS shapes quality
🧐 Enhances accuracy of of trip visualisation
🤓 Relation between PT operations and infrastructure unlocks wide range of modeling possibilities

Gonçalo F. Matos, Rosa Félix, Filipe Moura

Limit impacts of congestion
(Cesme et al. 2018)
Reducing travel time variability
(Surprenant-Legault and El-Geneidy 2011)
Increase commercial speed
(Basso et al. 2011)
Other modes can loose
quality of service
(Arasan and Vedagiri 2010)
Potential to jeopardize
public acceptance
(Batty et al. 2014)
It is crucial to underlie these interventions on data and evidence to ensure they are effective and accepted by the public


![]()

![]()

{
"agency_id": "41",
"bikes_allowed": true,
"capacity_seated": 29,
"capacity_standing": 28,
"capacity_total": 57,
"contactless": false,
"id": "41|300",
"license_plate": "AC-45-FH",
"make": "CaetanoBus",
"model": "e.City Gold",
"owner": "SCOTTURB",
"propulsion": "electricity",
"registration_date": "20141110",
"wheelchair_accessible": true,
"bearing": 167,
"block_id": "1_1325-11",
"current_status": "INCOMING_AT",
"event_id": "6KLCD-41|300-1612_0_2_0800_0829_0_1",
"lat": 38.76739501953125,
"line_id": "1612",
"lon": -9.2985200881958,
"pattern_id": "1612_0_2",
"route_id": "1612_0",
"schedule_relationship": "SCHEDULED",
"shift_id": "TP 1+1325",
"speed": 3.611111111111111,
"stop_id": "172486",
"timestamp": 1778574545,
"trip_id": "[6KLCD]1612_0_2_0800_0829_0_1",
"door_status": "CLOSED"
}Monitor operations in real-time
Monitor operations in real-time
GTFShift::get_route_frequency_hourly
![]()
GTFShift::osm_shapes_match_routes
![]()
GTFShift::get_way_frequency_hourly
osmdata::opq
![]()
GTFShift::osm_bus_lanes
GTFShift::rt_collect + GTFShift::rt_average_speed
![]()
sf::st_buffer
![]()
GTFShift::rt_extend_prioritization
Lisbon Metropolitan Area


Carris, Lisbon
Lisbon Metropolitan Area
Carris + Carris Metropolitana

📦 Open source R package
📊 Comprehensive framework for bus lane prioritization
🔎 Provides methods for the analysis of each individual dimension
🚀 Enables aggregated analysis with one simple method

🚀 Enables aggregated analysis with one simple method
library(GTFShift)
gtfs = GTFShift::load_feed("https://gateway.carris.pt/gateway/gtfs/api/v2.8/GTFS")
osm_q = opq(bbox=sf::st_bbox(tidytransit::shapes_as_sf(gtfs$shapes))) |>
add_osm_feature(key = "route", value = c("bus", "tram")) |>
add_osm_feature(key = "network", value = "Carris", key_exact = TRUE)
# Bus frequency 🚍, Number of lanes 🛣️, Network continuity 🌐
lanes = GTFShift::prioritize_lanes(gtfs, osm_q)
rt_collection = read.csv("rt_collect_file.csv") |>
sf::st_as_sf(coords = c("vehicle.position.longitude", "vehicle.position.latitude"), crs = 4326)
# Traffic conditions 🚗
lanes = GTFShift::rt_extend_prioritization(
lane_prioritization = lanes,
rt_collection = rt_collection
)What if we could analyse these dimensions altogether in an ✅open and ✅reproducible way?
What if we could analyse these dimensions altogether in an ✅open and ✅reproducible way?
What if we could make it accessible to everyone, without requiring coding skills?
Interactive dashboard to disseminate results
🗺️ Keep contributing to OSM
👀 Extend methods to evaluate operational performance
🌐 Apply methodology to international case studies
📄 Get papers published
💻 Submit to cran


An R tool to harmonise OSM and GTFS data
and assist in bus lane prioritisation
Gonçalo F. Matos, Rosa Félix, Filipe Moura

Gonçalo F. Matos, Rosa Félix, Filipe Moura