Search code examples
pythongraphvisualizationnetworkxdistance-matrix

How to make both edges (1edge starting from a node and 2ndedge ending in that node) bw two nodes in a directed (asym) graph using networkx in python?


I have a distance matrix of 50 cities. Sample matrix of the first 10 cities looks something like following:

0 1 2 3 4 5 6 7 8 9
0 0 Inf 1033.836 2954.445 Inf 570.7902 Inf 5201.642 927.6648 Inf
1 Inf 0 846.4284 2988.993 1739.0 586.6539 556.8027 4718.087 992.3883 Inf
2 1065.751 Inf 0 3713.848 2328.803 1293.154 922.5469 5968.72 1660.567 917.3977
3 3093.118 2721.323 3738.992 0 1386.044 2593.299 2926.249 2167.597 2188.789 2756.88
4 1547.838 1609.13 2530.782 1509.116 0 1071.186 Inf 3437.752 624.6915 1348.369
5 541.9545 603.5713 1270.946 2354.782 1026.145 0 204.1122 4501.91 436.0267 401.6861
6 459.8273 581.1262 1058.695 2634.319 1264.167 Inf 0 Inf 717.3868 300.6823
7 4815.335 5330.784 5322.427 2153.888 3612.119 4600.471 5372.185 0 3998.066 5173.963
8 789.3162 901.9897 1795.072 2139.049 635.1849 434.8522 738.8418 4598.177 0 775.1959
9 794.9219 244.2613 Inf 2964.827 1463.854 388.5041 297.126 5215.893 845.9431 0

There are 'inf' in the matrix where the cities are not connected, and 0 in the diagonals. I want to visualise the path from (say) city 3 to city 4 and from city 4 to city 3 also.

I want to visualise this matrix using networkx in python. I am not getting proper output as I expect. As per this question: (how to draw directed graphs using networkx in python?) and the answer given by raz, I was able to get the following graph with 'directed, and arrowhead' visualisation, Visualisation of an asymmetric distance matrix using the following code:

G = nx.DiGraph(directed=True)

num_nodes = 10 #considering only first 10 cities

for i in range(num_nodes):
    for j in range(num_nodes): 
        if (distance_matrix[i][j] != 0) and (distance_matrix[i][j] != np.inf):
            G.add_edge(i, j, weight=distance_matrix[i][j])


pos = nx.random_layout(G, seed=6)
edge_labels = {key: round(value, 3) for key, value in nx.get_edge_attributes(G, "weight").items()} #Doing this just to control the prescision of the distances

options = {
    'node_color': 'lightblue',
    'node_size': 100,
    'width': 1,
    'arrowstyle': '-|>',
    'arrowsize': 12,
}

plt.figure(figsize=(10, 10))
nx.draw_networkx(G, pos, arrows=True, **options)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=5)
plt.title("Distance Matrix Visualized as Graph")
plt.show()

I get this visualisation Visualisation of an asymmetric distance matrix.

Here, only one sided edges are being shown. I want both sided edges (with different values obviously) to be shown.

For example: edge from city 3 to city 4 has 1386.0443 and from city 4 to city 3 has 1509.1162 distance. But the graph only plots 1509.1162

Following code

print(G[4][3]['weight'])
print(G[3][4]['weight'])

yields:

1509.11627820888
1386.044382692059

i.e., the graph has the information about edges in both directions, but it is still showing only one sided edge.

I need help with correctly drawing both edges (i.e. one edge starting from a city and other one ending in that city) between any two cities in a directed asymmetric graph.


Solution

  • You may add some curvature to your edges (for example with the option 'connectionstyle': 'arc3,rad=-0.1') in both draw_networkx and draw_networkx_edge_labels:

    options = {
        'node_color': 'lightblue',
        'node_size': 100,
        'width': 1,
        'arrowstyle': '-|>',
        'arrowsize': 12,
        'connectionstyle': 'arc3,rad=-0.1',
    }
    
    nx.draw_networkx(G, pos, arrows=True, **options)
    nx.draw_networkx_edge_labels(G, pos, connectionstyle=options['connectionstyle'],
                                 edge_labels=edge_labels, font_size=5)
    

    Output:

    networkx digraph edge labels