3

I am trying to compare how ordered street networks are in comparison to randomly generated street networks.

As a starting point I have created a random graph with NetworkX with each node having a random location. I wanted to export this to a shapefile so that I can use it in ArcGIS. I checked the NetworkX documentattion and was elated to see that they have a write_shp() method. Their documentation mentions:

"Nodes and edges are expected to have a Well Known Binary (Wkb) or Well Known Text (Wkt) key in order to generate geometries. Also acceptable are nodes with a numeric tuple key (x,y)."

I decided to store the location of each node as a (x,y) tuple instead of including WKT as node's attributes.

Here is the code I am using:

g=nx.fast_gnp_random_graph(15, 0.25)

#Relabel Nodes
mapping=dict(zip(g.nodes(),"ABCDEFGHIJKLMNO"))
g=nx.relabel_nodes(g, mapping)

radius=100000  #100 Km

for d in g.nodes_iter(data=True): #I know this is a round about way to do this, but I might need node attributes later
        #Generate point location
        t = random.random() * (math.pi * math.pi)
        r = radius * math.sqrt(random.random())
        x = r * math.cos(t)
        y = r * math.sin(t)
        co_od=(x,y)
        nx.set_node_attributes(g, 'loc', {d[0]: co_od})

nx.write_shp(g, './shp/trialAgainShp')

I am getting the following error trace:

File "D:\ProgramFiles\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 699, in runfile
    execfile(filename, namespace)

  File "D:\ProgramFiles\Anaconda\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 74, in execfile
    exec(compile(scripttext, filename, 'exec'), glob, loc)

  File "C:/Users/Dipto/Desktop/CSProceedings_AuthorTools_Word_2003/createGrapg.py", line 62, in <module>
    nx.write_shp(g, './shp/trialAgainShp')

  File "D:\ProgramFiles\Anaconda\lib\site-packages\networkx\readwrite\nx_shp.py", line 183, in write_shp
    g = netgeometry(n, data)

  File "D:\ProgramFiles\Anaconda\lib\site-packages\networkx\readwrite\nx_shp.py", line 157, in netgeometry
    fkey = [float(x) for x in key]

ValueError: could not convert string to float: A

However, when I open the folder 'trialAgainShp', I do see shapefiles created with the name 'node', but they are empty.

I am not sure where I am going wrong


EDITS:

I tried 2 more things:

  1. I thought maybe the nodes have to have numeric labels to be converted to shapefiles and changing the label to alphabets was causing the failure.
  2. I tried adding WKT to each node with the following code as the last lines of the FOR loop:

        #Create WKT 
        wkt='POINT(' + str(x) + ' ' + str(y) + ')'
        print wkt
        nx.set_node_attributes(g, 'WKT', {d[0]: wkt})
    

The first option does not have any effect as the error remains the same. The second changes the error to the following:

...
nx.write_shp(g, './shp/trialAgainShp')

  File "D:\ProgramFiles\Anaconda\lib\site-packages\networkx\readwrite\nx_shp.py", line 183, in write_shp
    g = netgeometry(n, data)

  File "D:\ProgramFiles\Anaconda\lib\site-packages\networkx\readwrite\nx_shp.py", line 139, in netgeometry
    elif type(key[0]).__name__ == 'tuple':  # edge keys are packed tuples

TypeError: 'int' object has no attribute '__getitem__'
DotPi
  • 3,977
  • 6
  • 33
  • 53

1 Answers1

2

If you want to go for the tuple key, which I find reasonable, you have to store it the coordinates as the key of your node (not as an attribute).

Quick trial modifying a bit your code:

In [26]:

mapping = {}
counter = 0
for d in g.nodes_iter(data=True): #I know this is a round about way to do this, but I might need node attributes later
        #Generate point location
        t = random.random() * (math.pi * math.pi)
        r = radius * math.sqrt(random.random())
        x = r * math.cos(t)
        y = r * math.sin(t)
        co_od=(x,y)
        nx.set_node_attributes(g, 'loc', {d[0]: co_od})
        mapping[counter] = co_od
        counter += 1

In [28]:

g=nx.relabel_nodes(g, mapping)

In [29]:

nx.write_shp(g, '...')

Hope it helps.

lrnzcig
  • 3,868
  • 4
  • 36
  • 50
  • The only problem I found is that write_shp does not preserve the node and edge attributes. – DotPi Jan 21 '16 at 13:30
  • Hi! I think for that you have to use either Wkb or Wkt, but I honestly I haven't tried that myself. Maybe post some more details on what you are trying to do and I'll try to help. – lrnzcig Jan 21 '16 at 14:25
  • Hello! As far as I am aware, Wkt and hence by extension Wkb only has geometry information. I don't think there can be attribute information included in a Wkt. – DotPi Jan 21 '16 at 15:53
  • 1
    Sorry, you are right. By looking at the code in `networkx`, [link](https://github.com/networkx/networkx/blob/e0479d2e090ec301de9612330585e9bc8d1f967c/networkx/readwrite/nx_shp.py), the attributes should go GDAL fields, maybe [this](http://stackoverflow.com/questions/4215658/adding-custom-feature-attributes-to-esri-shapefile-with-python) helps you. – lrnzcig Jan 21 '16 at 16:15