pyrosm.graph_simplify.simplify_graph

Contents

pyrosm.graph_simplify.simplify_graph#

pyrosm.graph_simplify.simplify_graph(nodes, directed_edges, *, from_id_col='u', to_id_col='v', node_id_col='id', length_cols=('length',), edge_attrs_differ=('maxspeed', 'highway'), node_attrs_include=None, remove_rings=True, track_merged=False, edge_attr_aggs=None)#

Topologically simplify pyrosm’s directed graph-export edges.

Removes interstitial nodes (degree-2 nodes that only carry geometry) and collapses each chain of them into a single edge that keeps the full original geometry, matching the semantics of osmnx.simplification.simplify_graph. Operates on the directed representation pyrosm builds in get_directed_edges (two reciprocal rows per two-way street), before the data is handed to an exporter.

A chain is not merged across a change of maxspeed or highway (the default edge_attrs_differ; a missing value next to a set one counts as a change), so each simplified edge has one speed limit and one road class; edge_attrs_differ=None merges across them as OSMnx does by default.

A node with a value for one of node_attrs_include, a node column or a tag in the nodes’ tags, stays an end of its edges (a warning names a name no node has).

A simplified edge sums the length_cols of its segments. Other columns keep one value when it is the same along the chain, else become a list of the segments’ values; edge_attr_aggs aggregates a column instead, as in OSMnx: a dict of column -> function, called with the list of the segments’ values (e.g. {"travel_time_s": sum, "maxspeed_kmh": max}). By default (None) travel_time is summed, as OSMnx does.

Where two or more edges run between the same two consecutive nodes of a chain (typically duplicate OSM ways drawn over one street), only the first is kept, as in OSMnx. Parallel edges between two endpoints stay separate.

The implementation is graph-library free: it uses only numpy/pandas/shapely plus one Cython kernel (pyrosm._simplify_walk) for the inherently sequential chain walk. A pure Python reference walk (_reference_walk) is kept as a correctness oracle and as a fallback when the compiled kernel is unavailable.

The endpoint-detection and chain-collapsing rules follow OSMnx (osmnx.simplification.simplify_graph) and the topological simplification method described in:

Boeing, G. (2025). Topological Graph Simplification Solutions to the Street Intersection Miscount Problem. Transactions in GIS, 29: e70037. https://doi.org/10.1111/tgis.70037

directed_edges must be the directed representation (two reciprocal rows per two-way street), e.g. the output of pyrosm.graphs.get_directed_edges – NOT the single-row OSM.get_network(nodes=True) edges. Returns (simplified_nodes, simplified_edges) in the same schema the exporters consume.

Examples

Most users simplify as part of graph export (OSM.to_graph(..., simplify=True)):

from pyrosm import OSM, get_data

osm = OSM(get_data("helsinki_pbf"))
nodes, edges = osm.get_network(network_type="walking", nodes=True)
graph = osm.to_graph(nodes, edges, graph_type="networkx", simplify=True)

To run it directly on the directed edges and get GeoDataFrames back:

from pyrosm.graphs import get_directed_edges
from pyrosm.graph_simplify import simplify_graph

directed_nodes, directed_edges = get_directed_edges(
    nodes, edges, network_type="walking"
)
simple_nodes, simple_edges = simplify_graph(directed_nodes, directed_edges)