1

I'm trying to import a shapefile into networkx, but I'm not achieving my desired topology.

Networkx's read_shp() function seems to be deprecated, so I decided to import the shapefile as a GeoPandas dataframe and then convert this to a graph using the momepy package. This follows the example here, and my code is below, along with the graphical output.

The issue is that some road segments that are connected in the shapefile are not connected in my graph, and I'm wondering how I can achieve a graph with correct topology.

Based on my research so far, it seems like fiona and shapely may be useful tools, as seen in this post, but I'm not sure.

# Import shapefile into geopandas dataframe
path = "G:\\Shared drives\\DCR Team Drive\\Workspace\\Tehama_Evacuation_Strategy\\projects\\NateNightly\\tehema_networkx_analysis\\true_clip\\true_clip.shp"
df = gdp.read_file(path)
# Convert dataframe to primal graph via momepy
G = momepy.gdf_to_nx(df, approach="primal")

# Create plots and draw
f, ax = plt.subplots(1, 3, figsize=(18, 6), sharex=True, sharey=True)
df.plot(color='#e32e00', ax=ax[0])
for i, facet in enumerate(ax):
    facet.set_title(("Streets", "Primal graph", "Overlay")[i])
    facet.axis("off")
nx.draw(G, {n:[n[0], n[1]] for n in list(G.nodes)}, ax=ax[1], node_size=15)
df.plot(color='#e32e00', ax=ax[2], zorder=-1)
nx.draw(G, {n:[n[0], n[1]] for n in list(G.nodes)}, ax=ax[2], node_size=15)

shapefile, graph and overlay

0

1 Answer 1

1

Try adding vertices at each line intersection.

My shapefile looks like this, two separate clusters. The vertices are marked with squares:

enter image description here

import momepy
import geopandas as gpd
import networkx as nx
path = r"/home/bera/Desktop/GIStest/road_network.shp"

# Import shapefile into geopandas dataframe
df = gpd.read_file(path)
# Convert dataframe to primal graph via momepy
G = momepy.gdf_to_nx(df, approach="primal")
nx.draw(G)

There are five disconnected parts:

enter image description here

#Node the lines (Insert vertices at every line intersection)
diss = df.dissolve() #First dissolve all lines into one multiline
#                                             geometry  FID
# 0  MULTILINESTRING ((587634.565 6617367.431, 5880...    0

#Then extract each linestring and explode to a Series
singleparts = diss.apply(lambda x: [g for g in x.geometry.geoms], axis=1).explode() 
# singleparts.head(2)
# 0    LINESTRING (587634.5646364526 6617367.43126446...
# 0    LINESTRING (588018.5832143468 6616701.34594351...

df2 = gpd.GeoDataFrame(geometry=singleparts, crs=df.crs) #Create a new df from the singleparts Series
G2 = momepy.gdf_to_nx(df2, approach="primal")
nx.draw(G2)

Vertices have been inserted where there were none:

enter image description here

And the graph now have two parts:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.