5.1. Network Fundamentals and Data Acquisition#
5.1.1. Learning objectives#
By the end of this section, you should be able to:
describe a spatial network as a graph whose nodes and edges have locations and attributes;
choose between directed, undirected, weighted, and multigraph models;
explain how direction and parallel edges change a routing answer;
choose a study-area method and the query parameters that shape a downloaded graph;
explain what simplification does and why it changes node and edge counts;
convert a graph to node and edge layers and read its identifiers and units; and
record the provenance of a downloaded network.
Section goal
Build a correct mental model of a street network before downloading one. A small synthetic network with known lengths shows how direction, simplification, and units behave, and the same steps then run on a live OpenStreetMap query.
5.1.2. What makes a network spatial?#
A network is a graph whose nodes and edges have geographic locations and attributes. For a street network, nodes are usually intersections and endpoints, while edges are street segments. The attributes carry costs and constraints such as length, speed, travel time, access, and direction. Table 5.2 defines the terms used throughout this chapter.
Term |
Meaning |
In a street network |
|---|---|---|
Node |
A point where edges meet or end |
An intersection or a dead end |
Edge |
A connection between two nodes |
A street segment between intersections |
Directed edge |
A connection usable from |
One side of a one-way street |
Parallel edges |
Several edges joining the same two nodes |
A dual carriageway, or a service road beside a street |
Degree |
The number of edges that meet at a node |
An intersection where four streets meet |
Path |
A sequence of edges joining two nodes |
A route |
Weight (cost) |
A number on an edge that routing minimizes |
Length or travel time |
Connected component |
A set of nodes that can all reach one another |
A group of streets cut off from the rest |
OSMnx’s street_count attribute counts the physical streets at a node, so it differs
from the directed degree, which counts each direction separately.
OSMnx [Boeing, 2025] downloads OpenStreetMap features and builds NetworkX [Hagberg et al., 2008] graphs. A common result is a
MultiDiGraph: direction matters and multiple edges can connect the same pair of nodes.
That representation can model one-way streets and parallel carriageways, but the mode
and graph type must match the question. Table 5.3 lists the
choices.
Graph choice |
Use when |
|---|---|
Directed |
One-way or flow direction affects travel |
Undirected |
Direction is irrelevant or deliberately ignored |
Weighted |
Edges have a cost such as length or time |
MultiGraph |
Parallel connections must be retained |
The toy network below has six nodes at real coordinates near Columbia, Missouri. One street between nodes 2 and 5 is one-way, and nodes 3 and 6 are joined by two parallel edges, a street and a service road. Edge lengths are computed from the coordinates, in metres, the way OSMnx computes them.
6 nodes, 15 directed edges, 1 one-way, 2 parallel edges 3 -> 6
route 2 -> 5: 556 m
route 5 -> 2: 1,421 m via [5, 6, 3, 2]
undirected MultiGraph, route 5 -> 2: 556 m
Direction changes the answer. Going from node 2 to node 5 uses the one-way street and covers 556 m, but the return trip cannot use it and detours around the block for 1,421 m, about 2.6 times as far. The undirected copy ignores the restriction and reports 556 m in both directions, which is acceptable only when ignoring direction is the intent. The multigraph keeps both parallel edges between nodes 3 and 6, so a routing algorithm can choose between them, where a simple graph would silently keep only one.
5.1.3. Configure a small, repeatable query#
Network downloads use an external service [OpenStreetMap Contributors, 2026], and the query decides which graph comes back. Two choices matter most: how the study area is defined, and which parameters shape the graph. Table 5.4 lists the main ways to define the area.
Function |
The area is defined by |
Typical use |
Caution |
|---|---|---|---|
|
A geocoded place name or boundary |
A city or administrative unit |
Roads just outside the boundary are excluded |
|
An address and a distance |
The surroundings of a facility |
The distance can be a box or a network distance |
|
A coordinate and a distance |
A buffer around a known location |
Same choice of box or network distance |
|
A bounding box |
A rectangular study area |
Streets are cut at the rectangle |
|
Any polygon |
A custom or buffered study area |
The polygon must be in longitude and latitude |
Table 5.5 lists the parameters that change the graph itself.
Parameter |
What it controls |
Effect on the graph |
|---|---|---|
|
Which ways and access rules are included |
Different edges for driving, walking, or cycling |
|
A custom OpenStreetMap filter that replaces |
Full control, and full responsibility for the result |
|
Whether intermediate shape points become nodes |
Far fewer nodes and edges when |
|
Whether disconnected pieces are kept |
When |
|
How edges crossing the boundary are treated |
Keeps boundary-crossing edges when |
Simplification deserves a closer look because it changes every count. OpenStreetMap stores a street as a chain of nodes, including nodes that only mark a bend. A simplified graph keeps nodes at intersections and dead ends, and folds the bends into each edge: the edge stores the full shape as a geometry and the summed length. The toy chain below has two bend nodes between two endpoints.
raw: 4 nodes, 6 edges
simplified: 2 nodes, 2 edges
edge 1-4: length 536.3 m (raw chain 536.3 m), LineString with 4 vertices
Simplification removes the two bend nodes and the four edges they split, but not any
length: the single edge keeps all four vertices of the shape and the full 536 m.
Node and edge counts therefore depend on this one setting. A graph with simplify=False
holds a node at every bend, which inflates the counts and makes metrics such as
intersection density meaningless, so compare counts only between graphs built the same
way.
Cache responses while developing and keep the place and network type explicit. The query below downloads the drivable network of Columbia, Missouri, as a graph in longitude and latitude:
5766 13888 epsg:4326
The graph has 5,749 nodes and 13,854 directed edges, about 2.4 edges per node. Each two- way street contributes two directed edges, so the edge count is not a count of streets, and these numbers mean something only beside the query that produced them: drivable network, simplified, largest connected component.
Record the place or coordinates, query method, network type, retrieval date, and OSMnx version. A rerun can return a different graph because OpenStreetMap is edited continuously. OpenStreetMap data is licensed under the Open Database License [Open Data Commons, 2026, OpenStreetMap Contributors, 2026], so published results should credit “© OpenStreetMap contributors.”
{'place': 'Columbia, Missouri, USA', 'method': 'graph_from_place', 'network_type': 'drive', 'simplify': True, 'retain_all': False, 'osmnx_version': '2.1.1', 'retrieved': '2026-10-25', 'nodes': 5766, 'edges': 13888}
5.1.4. Network types are analytical choices#
The network_type decides which OpenStreetMap ways enter the graph and which access
rules apply, so it is part of the analytical question and not a technical default.
Table 5.6 lists the common types.
Network type |
Typical use |
Important assumption |
|---|---|---|
|
Vehicle routing |
One-way and access restrictions matter |
|
Pedestrian accessibility |
Paths and pedestrian links are included |
|
Cycling analysis |
Bikeable links and restrictions matter |
|
Exploratory infrastructure analysis |
It may include links unsuitable for a mode |
Do not compare node or edge counts across modes as if they were quality scores. The counts reflect different inclusion rules, coverage, and data completeness [Barrington-Leigh and Millard-Ball, 2017].
5.1.5. Convert a graph to spatial layers#
ox.graph_to_gdfs turns a graph into two GeoDataFrames, which are the bridge back to the
tools of Chapter 4. Nodes are indexed by their osmid and carry x, y, and
street_count. Edges are identified by the triple u, v, and key, which names the
start node, the end node, and which of several parallel edges it is. In current OSMnx
versions that triple is the index of the edge table, not a set of columns, so select it
after reset_index(); asking for u, v, and key directly raises a KeyError.
Units need the same care as in Chapter 4. The length attribute is in metres, computed
by OSMnx, whatever the CRS. The geometry of an unprojected graph is in degrees, so
geometry-based lengths and areas need a projected graph first. The cell below shows all
three on the toy network.
x y street_count geometry
osmid
1 -92.340 38.95 2 POINT (-92.34 38.95)
2 -92.335 38.95 3 POINT (-92.335 38.95)
3 -92.330 38.95 3 POINT (-92.33 38.95)
edge index: ['u', 'v', 'key']
u v key length geometry
0 1 2 0 432.379220 LINESTRING (-92.34 38.95, -92.335 38.95)
1 1 4 0 555.975419 LINESTRING (-92.34 38.95, -92.34 38.955)
2 2 1 0 432.379220 LINESTRING (-92.335 38.95, -92.34 38.95)
graph CRS: EPSG:4326 -> EPSG:32615
first edge, geometry length unprojected: 0.0050 (degrees)
first edge, geometry length projected: 433.3 m
first edge, length attribute: 432.4 m
The two metric lengths differ slightly because the attribute is a great-circle distance
between the end points and the projected geometry is measured on a plane. Use the
length attribute for routing, and project the graph before any geometric measurement.
The same conversion on the Columbia graph, with the identifiers selected correctly, is:
| x | y | street_count | geometry | |
|---|---|---|---|---|
| osmid | ||||
| 93201793 | -92.257014 | 38.960200 | 3 | POINT (-92.25701 38.9602) |
| 93201794 | -92.249907 | 38.959998 | 3 | POINT (-92.24991 38.96) |
| 189092378 | -92.271379 | 38.970326 | 3 | POINT (-92.27138 38.97033) |
| 189092380 | -92.272582 | 38.970309 | 4 | POINT (-92.27258 38.97031) |
| 189092382 | -92.273699 | 38.970326 | 4 | POINT (-92.2737 38.97033) |
| u | v | key | length | geometry | |
|---|---|---|---|---|---|
| 0 | 93201793 | 415348196 | 0 | 273.551063 | LINESTRING (-92.25701 38.9602, -92.25658 38.96... |
| 1 | 93201793 | 93201794 | 0 | 615.061647 | LINESTRING (-92.25701 38.9602, -92.25659 38.96... |
| 2 | 189092378 | 189092380 | 0 | 104.044748 | LINESTRING (-92.27138 38.97033, -92.27258 38.9... |
| 3 | 189092378 | 189116732 | 0 | 131.430378 | LINESTRING (-92.27138 38.97033, -92.27136 38.9... |
| 4 | 189092378 | 189116734 | 0 | 220.398589 | LINESTRING (-92.27138 38.97033, -92.27132 38.9... |
The head rows show the shape of a simplified graph. Nodes are junctions with 3 or 4 streets, and an edge between neighbouring junctions can be 104 m or 615 m long because bends are folded into it. Node identifiers are large OpenStreetMap ids, so keep them as integers.
Nodes are point geometries and edges are usually line geometries. The u, v, and
key values identify an edge in a multigraph. length is normally in meters for
OSMnx graphs, but confirm the graph CRS and metadata before relying on the unit.
5.1.6. Summary#
Start with a graph model that reflects the movement question: direction, parallel edges, and the cost on each edge all change the answer. Select a network type and study area deliberately, understand that simplification changes every count, cache the source response, inspect the graph metadata, and keep node and edge layers available for spatial inspection, remembering that lengths are in metres but unprojected geometry is in degrees. Record the query, date, version, and licence with every graph.