5.2. Query Scope and Network Topology#
5.2.1. Learning objectives#
By the end of this section, you should be able to:
choose a study-area method and check a boundary before using it;
explain boundary effects and why features near the edge of a study area need care;
distinguish a bounding-box radius from a network-distance radius;
decide when to simplify a graph, and which analyses need the raw nodes;
distinguish weak from strong connectivity and clean a graph accordingly;
explain what converting a graph discards, namely direction and parallel edges; and
document every derived representation of a network.
Section goal
The query defines the graph, and the graph defines every later answer. Small synthetic networks with known structure show how extent, distance rules, connectivity, and conversions change a network, and the same checks then run on Columbia, Missouri.
5.2.2. Choose the spatial extent#
OSMnx offers several ways to define a study area. Each method answers a slightly
different question, and Table 5.7 extends the function list of
S01 with the two distance rules of graph_from_point.
Query |
Best use |
Limitation |
|---|---|---|
|
A geocoded administrative or named place |
Depends on the returned boundary |
|
A custom irregular study area |
Requires a valid polygon |
|
A rectangular tile or quick test |
Includes everything in the rectangle |
|
A fast approximate radius |
Distance is not along the network |
|
A reachable network around a point |
More computation and a mode-specific result |
A named place is only as good as the boundary the geocoder returns. Before building a graph from it, check that the result is the intended OpenStreetMap object (a name can match several), that its bounds are plausible for the place, and that its geometry is a polygon. Inspect a boundary before using it:
name osm_type osm_id
0 Columbia relation 141403
epsg:4326 [-92.433832 38.863537 -92.2276844 39.029402 ]
The geocoder returned a single OpenStreetMap relation for Columbia, with longitude and
latitude bounds roughly 0.2 degrees across, which is plausible for a city. A polygon boundary
is also what makes graph_from_polygon repeatable: the same polygon returns the same
extent on every run.
5.2.2.1. Boundary effects#
A study-area boundary cuts streets, and the cut changes what the network says near the edge. A node whose neighbours lie outside the boundary loses edges, so its degree, its centrality, and the distances through it are all understated. The pattern is called a boundary effect [Gil, 2017], and the practical rule is to measure features well inside the study area, or to download a larger area and analyze only its interior. The toy street grid below has 81 nodes 100 m apart. A 5 by 5 study area is cut from the middle and the number of four-way intersections is counted again.
full grid: 81 nodes; study area keeps 25
four-way intersections among the kept nodes: 25 in the full grid, 9 after clipping
All 25 kept nodes are four-way intersections in the full grid, but only the inner 9 still look like one after clipping, because the 16 nodes on the new edge have lost their outward streets. An intersection-density or degree statistic computed on the clipped graph would describe the boundary, not the city.
5.2.2.2. Two ways to define a radius#
A radius around a point can mean two different areas. With dist_type="bbox" it is a
square of half-width dist around the point, which contains every street inside the
square whether or not it can be reached. With dist_type="network" it is the set of nodes
within network distance dist of the point, so rivers, rail lines, and missing links
shrink it. The next cell compares the two on the grid, with and without a river that has
no crossing near the centre.
bounding box, 250 m half-width: 25 nodes
network distance, 250 m, no river: 13 nodes
network distance, 250 m, river with no crossing: 9 nodes
The square holds 25 nodes whatever the river does. The network radius is 13 nodes on an open grid, because only nodes within two blocks of travel qualify, and falls to 9 when the river removes everything north of the centre. The box says what is near, and the network radius says what is reachable. The same difference appears on real Columbia data:
2743 1544
The network rule keeps 1,544 of the 2,743 nodes that the box holds, 44% fewer, so the walkable catchment is much smaller than the square around it.
Network distance is more realistic for accessibility [Apparicio et al., 2008, Geurs and Van Wee, 2004], while a bounding box can be useful for a quick, reproducible tile. The two graphs should not be treated as equivalent study areas.
5.2.3. Simplification changes the graph#
Raw OpenStreetMap geometry contains points along curves. With simplify=True, OSMnx [Boeing, 2017] removes intermediate shape nodes while retaining the edge geometry, so graph nodes more
closely represent intersections and endpoints, as the toy chain in S01
showed. Simplification is useful for routing and statistics, but an analysis of raw OSM
vertices should leave it disabled. Table 5.8 says which analyses
need which.
Analysis |
Simplify? |
Reason |
|---|---|---|
Routing and shortest paths |
Yes |
Same lengths with far fewer nodes |
Intersection counts, degree, and centrality |
Yes |
Nodes should be intersections and dead ends |
Snapping points to street vertices, or measuring curvature |
No |
The bend nodes carry the information |
Comparing node counts between graphs |
Same setting for all |
Counts depend directly on the setting |
Simplification is not the last step for intersection counts. A single junction mapped as several close nodes, such as a dual carriageway crossing, is still counted several times, and OSMnx can merge them with a tolerance in a projected graph.
raw: 536
simplified: 96
Simplification removes 440 of the 536 raw nodes, 82% of them, and leaves every edge’s length intact because the shape moves into the edge geometry.
5.2.4. Connectivity: weak and strong components#
A connected component is a set of nodes that can reach one another, and on a directed graph there are two ways to define it. Table 5.9 compares them.
Type |
Nodes are connected when |
Routing consequence |
|---|---|---|
Weak |
A path exists if directions are ignored |
The pieces touch, but a route may still be impossible |
Strong |
A path exists in both directions, obeying direction |
Every node can route to every other |
retain_all=False commonly keeps only the largest weakly connected component, and
retain_all=True keeps the islands, which is right when they are meaningful to the study.
Dropping islands is usually harmless, but a weakly connected graph can still contain a trap: a
group of streets that can be entered but not left because every link out is one-way the
wrong way. The toy graph below has a chain of two-way streets 1 to 4 and a pair of nodes
5 and 6 reached by a one-way street from node 3.
weak components: 1
strong components: 2
route 1 -> 6 exists: True
route 6 -> 1 exists: False
nodes in the largest strong component: [1, 2, 3, 4]
The graph is weakly connected, so a weak-component check passes, yet it has two strong
components: a route from node 1 to node 6 exists, and the way back does not. A routing
workflow that picks origins and destinations inside the trap would fail or return nonsense.
largest_component(strongly=True) keeps only the nodes that can reach one another, and the
choice between weak and strong should be recorded with the graph.
5.2.5. Check direction and parallel edges#
The checks below count the one-way and parallel edges of the simplified drivable graph:
directed: True
multigraph: True
weak components: 1
14 0
The graph is directed, a multigraph, and weakly connected, with 14 one-way edges and no parallel edges. Its strong connectivity is a separate question, answered on the same graph by the cell below.
strong components: 4
nodes before and after keeping the largest strong component: 96 93
The drivable graph has four strong components, but only three nodes fall outside the largest one: the 93 retained nodes leave 3 of the 96, so each of the other three components is a single node (an entry or exit that cannot be used in both directions). Losing 3% of the nodes is small, yet any route that starts or ends at one of them would fail, which is why the strong component is the one to keep for routing.
5.2.6. What a conversion discards#
Every simpler graph type discards something, and Table 5.10 lists what. Converting a graph is sometimes justified, for a metric that is defined only on simple graphs, for example, but each conversion should be a deliberate and recorded choice.
Conversion |
What it erases |
Consequence |
|---|---|---|
|
Direction |
One-way restrictions disappear, as in S01 |
|
Parallel edges |
Only one of several edges survives |
|
Parallel edges, by a stated rule |
The shortest parallel edge is kept |
The collapse of parallel edges is the less obvious loss. A plain conversion keeps one edge without regard for its cost. The toy pair below has a 300 m street and a 450 m service road between the same two nodes, and the service road is added second.
multigraph, shortest a -> b: 300 m
nx.DiGraph(G), edge a -> b: 450 m
to_digraph(G, weight='length'): 300 m
The plain DiGraph kept the last edge, the 450 m service road, so every route through the
pair is now 150 m longer than the real shortest route, and nothing reports the change.
to_digraph with an explicit weight keeps the 300 m street, which is the defensible rule
here.
Do not convert a directed multigraph merely to make a statistic easier. Converting to an undirected graph can erase one-way restrictions, and collapsing parallel edges can discard a legitimate route choice. Preserve the original graph and document every derived representation.
5.2.7. Summary#
Query extent, network distance, simplification, component retention, and direction all change the meaning of a network. Keep the analysis well inside the boundary to avoid edge effects, choose a network radius when reachability is the question, simplify only when the analysis wants intersections as nodes, and use strong connectivity when routes must work in both directions. Make those choices before comparing graphs or calculating a route.