7

I am being baffled by how apparently poorly NetworkX reads a shapefile and builds a graph out of it.

Below is a graphical example of a fake network built with 27 polylines all snapped together, so there are no topological errors (ArcGIS 10.3.1, License: Advanced). The coordinate system is the British National Grid (OSGB36).

enter image description here

Now, when doing

import networkx as nx
import matplotlib.pyplot as plt

G=nx.read_shp('C:\Users\MyName\MyFolder\TEST.shp') 
nx.draw(G, with_labels=False)

The result is a graph plotted according to the spring layout, so the shape of the file is not preserved. Also, the image shows three disconnected components, which are absolutely fabricated, since all segments in my shapefile were snapped. Also, the coordinates of the nodes are imported as labels.

enter image description here

I wonder what the usefulness of the nx.read_shp() function is, if you are not allowed to reproduce the shapefile exactly. This is especially true if you want to make sure that the connections are recreated accurately.

This leads me to my question: how to play with NetworkX so that the graph is not plotted in some meaningless way, but reproduces the network shown in the shapefile?

2 Answers 2

14

I might have found a nice Python solution referring to the very shapefile in the question, so I am posting it for future reference.

import networkx as nx
import matplotlib.pyplot as plt

G=nx.read_shp('C:\Users\MyName\MyFolder\TEST.shp') 
pos = {k: v for k,v in enumerate(G.nodes())}
X=nx.Graph() #Empty graph
X.add_nodes_from(pos.keys()) #Add nodes preserving coordinates
l=[set(x) for x in G.edges()] #To speed things up in case of large objects
edg=[tuple(k for k,v in pos.items() if v in sl) for sl in l] #Map the G.edges start and endpoints onto pos
nx.draw_networkx_nodes(X,pos,node_size=100,node_color='r')
X.add_edges_from(edg)
nx.draw_networkx_edges(X,pos)
plt.xlim(450000, 470000) #This changes and is problem specific
plt.ylim(430000, 450000) #This changes and is problem specific
plt.xlabel('X [m]')
plt.ylabel('Y [m]')
plt.title('From shapefiles to NetworkX')

Result and comparison. The final shape of the network might be shrinked in some direction, this depending on the plt.xlim() and plt.ylim() values used. With plt.figure(figsize=(10,10)) or other squares things might improve. enter image description here

6
  • 1
    glad it worked out. Feb 10, 2017 at 15:33
  • Someone finds it funny to downvote random answers/questions without saying why. Appalling.
    – FaCoffee
    Feb 14, 2017 at 17:01
  • @FaCoffee What about if we have to convert shapefile to a MultiDigraph
    – osmjit
    May 22, 2017 at 15:24
  • 1
    @osmjit This is an interesting question. As a starting point, I think you should look into NetworkX's function that creates MultiDiGraphs. Then, you need to figure out how to define edge directionality. If your goal is to model networks such as the power grid, my suggestion would be to use a simplified scheme, if possible. For example, this would involve turning multiple edges between two nodes into a unique edge. Hope this helps.
    – FaCoffee
    May 22, 2017 at 15:30
  • @FaCoffee Digraphs are workable in networkx but the needs to hadle the multiple egdes into same node. Can you please make it more clear due to newwbie to networkx. it would be great help and I am stuck.
    – osmjit
    May 22, 2017 at 15:36
4

That will pretty much depend on how your shapefile is. Is it segmented (the lines break, when they encounter intersections)?

I haven't used read_shp for networkx, so I'm not sure.

I guess that read_shp might do some work trying to figure everything out and that might be related to a precision issue. That should be configurable, but it's not.

Looking at the source (https://networkx.github.io/documentation/development/_modules/networkx/readwrite/nx_shp.html#read_shp) you can see that networkx uses coordinate pairs as the keys. A slight difference in one of the keys will show what you are seeing, disconnected nodes/edges.

Try to investigate the nodes of the disconnected patches. I'm pretty sure one of the nodes have quite similar coordinates, but slightly different, thus making it another node.

Your Answer

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

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