Building-to-service travel-time matrix

This notebook computes the matrix of travel times from the example buildings to the example services on an intermodal graph (walk + public transport) with IduEdu’s od_matrix and stores it in examples_data/matrix_time.parquet for the provision example.

The last section, Your own area, explains how to compute the matrix for another territory.

# !pip install "iduedu[pbf]" pyarrow
import geopandas as gpd
import iduedu
import pandas as pd
from iduedu import get_intermodal_graph, od_matrix
from shapely.ops import unary_union

1. Buildings and services

# Read building and service datasets
buildings = gpd.read_parquet('examples_data/buildings.parquet')
services = gpd.read_parquet('examples_data/services.parquet')

2. Territory

The convex hull of all buildings and services, buffered by 0.001° (about 60–110 m), defines the graph extent.

polygon = unary_union(
    buildings.to_crs(4326).geometry.to_list() + services.to_crs(4326).geometry.to_list()
).convex_hull.buffer(0.001)

3. Intermodal graph

The territory is cut out of the Geofabrik extract of the Northwestern Federal District (iduedu.use_pbf); the same call without the with block downloads the data from the Overpass API.

with iduedu.use_pbf(territory=polygon, region="northwestern-fed-district"):
    G_intermodal = get_intermodal_graph(territory=polygon, clip_by_territory=True)
2026-11-04 22:07:48.449 | WARNING  | Removing 407 nodes outside the largest strongly connected component. Retaining 21326 of 21733 nodes.
2026-11-04 22:07:48.470 | WARNING  | Public transport nodes dropped with the smaller components: {'trolleybus': 2}

4. Travel-time matrix

od_matrix snaps origins and destinations to graph nodes and runs Dijkstra searches with the edge weight weight ("time_min", minutes) up to threshold (45 minutes). Pairs beyond the threshold are unreachable.

# Compute travel time matrix (in minutes)
matrix: pd.DataFrame = od_matrix(
    G_intermodal,
    gdf_origins=buildings,
    gdf_destinations=services,
    weight="time_min",
    threshold=45,
)

5. Storage

The matrix is stored for the provision example.

# Save matrix to Parquet format
# IduEdu returns a sparse DataFrame to keep large OD matrices compact in memory.
# Parquet writers do not support pandas SparseDtype columns, so convert to a dense
# DataFrame before saving. Unreachable pairs stay encoded as np.inf.
matrix_dense = matrix.sparse.to_dense()
matrix_dense.to_parquet('examples_data/matrix_time.parquet')

6. Your own area

The notebook is the recipe for another area: put your buildings and services (GeoDataFrames in any CRS) into buildings and services in section 1 and run it. The territory around them, the graph and the matrix are then computed from them; iduedu.use_pbf chooses the Geofabrik extract itself when region is left out. Save the matrix under your own name and pass it to get_service_provision as in the provision example.