@@ -12,6 +12,7 @@ jupyter:
1212 name : python3
1313---
1414
15+ <!-- #region editable=true slideshow={"slide_type": ""} -->
1516# Representing geographic data as networks
1617
1718Contents:
@@ -21,8 +22,10 @@ Contents:
2122- How to create a graph from a file representing streets
2223- How to create a routable graph from OpenStreetMap
2324- Other uses of graphs - morphology, spatial weights, etc.
25+ - Saving graphs to disk
26+ <!-- #endregion -->
2427
25-
28+ <!-- #region editable=true slideshow={"slide_type": ""} -->
2629## Basic concepts
2730
2831As we briefly introduced in Chapter 5.2, networks are data structures that consists of nodes that are connected to other nodes via edges which ultimately construct a network (or a graph as it is referred in graph theory). As networks are widely used in various domains, the names used for these basic elements of a network can sometime vary. To clarify some of the ambiguity related to these terms, we list commonly used terms related to spatial networks below:
@@ -35,7 +38,7 @@ In Python, most of the network analysis related libraries (e.g. `networkx`, `igr
3538
3639
3740
38-
41+ <!-- #endregion -->
3942
4043## Creating a simple graph from scratch
4144
@@ -175,7 +178,7 @@ positions = {node: attrs["coords"] for node, attrs in G2.nodes.data()}
175178edge_labels = {(u, v): attrs[" weight" ] for u, v, attrs in G2.edges.data()}
176179```
177180
178- ``` python
181+ ``` python editable=true slideshow={"slide_type": ""}
179182nx.draw(G2,
180183 with_labels = True ,
181184 pos = positions,
@@ -191,12 +194,169 @@ nx.draw_networkx_edge_labels(
191194);
192195```
193196
197+ ``` python editable=true slideshow={"slide_type": ""}
198+ distance, path = nx.single_source_dijkstra(G = G2,
199+ source = " a" ,
200+ target = " e" ,
201+ weight = " weight" ,
202+ )
203+ ```
204+
205+ ``` python
206+ print (" Distance:" , distance)
207+ print (" Path / visited nodes:" , path)
208+ ```
209+
210+ ``` python
211+ distance, path = nx.single_source_dijkstra(G = G2,
212+ source = " e" ,
213+ target = " a" ,
214+ weight = " weight" ,
215+ )
216+ ```
217+
218+ ``` python
219+ print (" Distance:" , distance)
220+ print (" Path / visited nodes:" , path)
221+ ```
222+
223+ ``` python
224+ path_edges = list (zip (path,path[1 :]))
225+ path_edges
226+ ```
227+
228+ ``` python
229+ nx.draw(G2,
230+ with_labels = True ,
231+ pos = positions,
232+ font_color = " white" ,
233+ node_color = " grey" )
234+
235+ nx.draw_networkx_nodes(G2, positions, nodelist = path, node_color = ' r' )
236+ nx.draw_networkx_edges(G2, positions, edgelist = path_edges, edge_color = ' r' , width = 3 );
237+ ```
238+
194239### Directed graph
195240
196241``` python
197- G2 = nx.MultiDiGraph()
242+ G_directed = nx.MultiDiGraph()
243+ ```
244+
245+ ``` python
246+ node_collection = [(" a" , {" coords" : (0 ,5 )}),
247+ (" b" , {" coords" : (5 ,5 )}),
248+ (" c" , {" coords" : (0 ,0 )}),
249+ (" d" , {" coords" : (5 ,0 )}),
250+ (" e" , {" coords" : (10 ,0 )}),
251+ ]
252+ ```
253+
254+ ``` python
255+ edge_collection = [(" a" , " b" , {" weight" : 1 , " color" : " red" }),
256+ # bidirectional a<->c
257+ (" a" , " c" , {" weight" : 2 , " color" : " green" }),
258+ (" c" , " a" , {" weight" : 2 , " color" : " green" }),
259+ # bidirectional b<->d
260+ (" b" , " d" , {" weight" : 1 , " color" : " green" }),
261+ (" d" , " b" , {" weight" : 1 , " color" : " green" }),
262+
263+ (" c" , " d" , {" weight" : 1 , " color" : " red" }),
264+ (" d" , " e" , {" weight" : 3 , " color" : " red" }),
265+ ]
266+ ```
267+
268+ ``` python
269+ # Add nodes and edges from the collections
270+ G_directed.add_nodes_from(node_collection)
271+ G_directed.add_edges_from(edge_collection)
272+
273+ # Extract exact node locations
274+ positions = {node: attrs[" coords" ] for node, attrs in G_directed.nodes.data()}
275+
276+ # Parse edge labels
277+ edge_labels = {(u, v): attrs[" weight" ] for u, v, attrs in G_directed.edges.data()}
278+
279+ # Parse edge colors
280+ edge_colors = [attrs[" color" ] for u, v, attrs in G_directed.edges.data()]
281+ ```
282+
283+ ``` python
284+ nx.draw(G_directed,
285+ with_labels = True ,
286+ pos = positions,
287+ font_color = " white" ,
288+ node_color = " grey" ,
289+ edge_color = edge_colors
290+ )
291+
292+ nx.draw_networkx_edge_labels(
293+ G_directed,
294+ positions,
295+ edge_labels = edge_labels,
296+ font_color = ' red' ,
297+ font_weight = " bold" ,
298+ );
299+ ```
300+
301+ ``` python editable=true slideshow={"slide_type": ""}
302+ distance, path = nx.single_source_dijkstra(G = G_directed,
303+ source = " a" ,
304+ target = " e" ,
305+ weight = " weight" ,
306+ )
198307```
199308
200309``` python
310+ path_edges = list (zip (path,path[1 :]))
311+ path_edges
312+ ```
313+
314+ ``` python
315+ nx.draw(G_directed,
316+ with_labels = True ,
317+ pos = positions,
318+ font_color = " white" ,
319+ node_color = " grey" )
320+
321+ nx.draw_networkx_nodes(G_directed, positions, nodelist = path, node_color = ' r' )
322+ nx.draw_networkx_edges(G_directed, positions, edgelist = path_edges, edge_color = ' r' , width = 3 );
323+ ```
324+
325+ #### Question 8.1
326+
327+ What is the path length and route from ` e ` to ` a ` using the directed graph?
328+
329+ ``` python editable=true slideshow={"slide_type": ""}
330+ # You can use this cell to enter your solution.
331+ ```
332+
333+ ``` python editable=true slideshow={"slide_type": ""} tags=["remove_book_cell", "hide-cell"]
334+ # Solution
335+
336+ # This is a trick question: Because our graph is directed
337+ # and there is no way out from node 'e', there is no path nor length
338+ # from e to a
339+
340+ # When searching for such a path, networkx raises an error
341+
342+ # Uncomment to test yourself
343+ # distance, path = nx.single_source_dijkstra(G=G_directed, source="e", target="a", weight="weight")
344+ ```
345+
346+ <!-- #region editable=true slideshow={"slide_type": ""} -->
347+ ## Creating a graph from LineStrings
348+ <!-- #endregion -->
349+
350+ <!-- #region editable=true slideshow={"slide_type": ""} -->
351+ Data was obtained from
352+ <!-- #endregion -->
353+
354+ ``` python editable=true slideshow={"slide_type": ""}
355+ import geopandas as gpd
356+ import momepy
357+ from contextily import add_basemap
358+ ```
359+
360+ ``` python editable=true slideshow={"slide_type": ""}
201361
202362```
0 commit comments