问题
I am running a loop that computes a networkx.classes.multidigraph.MultiDiGraph
for each row (neighbourhood) of a list of GeoDataFrames (cities). It then computes some statistics for each row and writes the file out to disk. The problem is that the loop is extremely long to compute because the graph is computed for each row.
The way I want to quicken the loop is by computing the graph for the whole GeoDataFrame and then clipping the graph into each row (each row has a polygon). You can do this for GeoSeries with geopandas.clip
. It seems, however, that no equivalent to geopandas.clip
exists for networkx graphs.
Does anyone know of a way to clip a networkx graph?
Alternatively, what other methods exist to speed up my loop.
Note: clipping would work if I could convert the networkx graph to a pandas object. Unfortunately, I think it is not possible to keep the properties which osmnx acts on when the graph is converted to a pandas object. If I'm wrong, please say so.
Here is my initial code:
import osmnx as ox
import pandas as pd
import geopandas as gpd
import os
path="C:/folder/"
files=[os.path.join(path, f) for f in os.listdir(path)]
for i in range(0,2):
city=gpd.read_file(files[i])
circ=[]
for i in range(0,181):
graph_for_row=ox.graph_from_polygon(city.geometry[i])
#above is the long command
stat = ox.basic_stats(graph_for_row)
circ.append(stat['circuity_avg'])
circ=pd.Series(circ)
merged.append(pd.concat([city, circ], axis=1))
for i in (range(0,len(merged))):
with open(geofiles[i], 'w') as f:
f.write(merged[i].to_json())
Here is the new loop I'm aiming for:
clipped_graph=[]
for i in range(0,2):
city=gpd.read_file(files[i])
whole_city=city.unary_union
graph=ox.graph_from_polygon(whole_city)
clipped_graph.append(gpd.clip(graph, city.geometry))#this line
#does not work since 'graph' is a networkx object, not
#a GeoDataFrame or GeoSeries
circ=[]
for i in range(0,181)
stat = ox.basic_stats(clipped_graph[i])
circ.append(stat['circuity_avg'])
circ=pd.Series(circ)
merged.append(pd.concat([city, circ], axis=1))
for i in (range(0,len(merged))):
with open(geofiles[i], 'w') as f:
f.write(merged[i].to_json())
回答1:
You can use your individual polygons to (spatially) intersect the graph nodes, then use those nodes to induce a subgraph. MWE:
import osmnx as ox
ox.config(use_cache=True, log_console=True)
# load a shapefile of polygons as geodataframe using geopandas
# here i just get 3 cities from OSM to make example reproducible without a shapefile
places = ['Cudahy, CA, USA', 'Bell, CA, USA', 'Maywood, CA, USA']
gdf = ox.gdf_from_places(places)
# get a graph of the union of their boundaries, then extract nodes as geodataframe
G = ox.graph_from_polygon(gdf.unary_union, network_type='drive')
nodes = ox.graph_to_gdfs(G, edges=False)
# for each city polygon, find intersecting nodes then induce subgraph
for polygon in gdf['geometry']:
intersecting_nodes = nodes[nodes.intersects(polygon)].index
G_sub = G.subgraph(intersecting_nodes)
fig, ax = ox.plot_graph(G_sub)
来源:https://stackoverflow.com/questions/60268145/clipping-a-networkx-graph-according-to-georeferenced-polygon