I am using OSMnx to return roadmaps, which are represented as MultiDiGraphs in networkx.
import osmnx as ox
%matplotlib inline
sg = ox.graph_from_point((37.7936516, -122.4503161), distance=100, network_type='all_private')
ox.plot_graph(sg)
This returns a graph of five nodes (blue dots) connected by six edges (gray).
You'll notice that two nodes have two edges connecting them (in the lower right). So if you look at sg[a][b]
you'll get a different edge than sg[b][a]
. But if you pull sg[c][d]
there is not always a sg[d][c]
(because of one-way roads).
I'd like to convert this to a MultiGraph, so I run sg_u = sg.to_undirected()
which creates the missing sg[d][c]
. But unfortunately it also overwrites existing "reverse" edges.
It's easy to see if looking at the 'length' attributes:
sg[65283442][65283457]
has a length of 85.36 (m, presumably)
sg[65283457][65283442]
has a length of only 41.62
But after running to_undirected()
both have lengths of 41.62.
Is there anyway to simply add the new "reverse" edge rather than redefine it?
OSMnx has a built-in function get_undirected to handle the quirks of converted a MultiDiGraph of a street network to a MultiGraph.
import osmnx as ox
%matplotlib inline
sg = ox.graph_from_point((37.7936516, -122.4503161), distance=100, network_type='all_private')
sgu = ox.get_undirected(sg)
print(sgu[65283457][65283442])
Prints:
{0: {'from': 65283442,
'geometry': <shapely.geometry.linestring.LineString at 0x1a0c10b67b8>,
'highway': 'residential',
'length': 85.36240139096256,
'oneway': True,
'osmid': 8915222,
'to': 65283457},
1: {'from': 65283457,
'geometry': <shapely.geometry.linestring.LineString at 0x1a0c10b64a8>,
'highway': 'residential',
'length': 41.620571785809716,
'oneway': True,
'osmid': 8915224,
'to': 65283442}}
sgu
is a MultiGraph. As you can see, it retains two (ie, parallel) undirected edges between these nodes and all of the attributes of each.
Also, yes, the OSMnx graph edge lengths are in meters by default.