networkx plotting directed graph

Viewed 1284

I'm trying to create a directed graph with weighted edges from the networkx library. The graph as shown in the picture is what im trying to achieve

Picture of 1 router and 2 nodes, communicating with known speeds

This is the code I've got so far

import networkx as nx
import matplotlib.pyplot as plt
import pandas as panda

df = panda.DataFrame({'from':['R','R','D04','D04','D06','D06'], 'to':['D04','D06','R','D06','R','D04']})
    G=nx.from_pandas_edgelist(df, 'from', 'to', create_using=nx.DiGraph()) 


    G['R']['D04']['weight'] = 243.0
    G['R']['D06']['weight'] = 150.0
    G['D06']['D04']['weight'] = 211.0
            

    pos = nx.spring_layout(G)
    labels = nx.get_edge_attributes(G,'weight')
    nx.draw_networkx_edge_labels(G,pos, edge_labels=labels)

    # Make the graph
    nx.draw(G, with_labels=True, node_size=1500, alpha=0.3, font_weight="bold", arrows=True)


    plt.axis('on')
    plt.show()

Pictures of what im getting:

Result1

Result2

I'm having a hard time figuring out how to enable the X/Y-axis. I don't know the placement of the different nodes, only that the Router node ('R') should be placed in (0,0). Furthermore my edge weights seem to be placed at random. Sometimes they are placed nicely, other times they go flying off. And lastly the directed edges seem to be straight, and not bent as wished. I've read there should be an attribute called 'connectionstyle', but just can't seem to get it working.

1 Answers

The problem is that the spring layout is intended for much more complex networks, where you wouldn't want to control the positioning. In this case, you want to override the node placement algorithm (I think) by setting fixed positions, like this:

import networkx as nx
import matplotlib.pyplot as plt
import pandas as panda
df = panda.DataFrame({'from':['R','R','D04','D04','D06','D06'], 'to':['D04','D06','R','D06','R','D04']})
G=nx.from_pandas_edgelist(df, 'from', 'to', create_using=nx.DiGraph()) 
G['R']['D04']['weight'] = 243.0
G['R']['D06']['weight'] = 150.0
G['D06']['D04']['weight'] = 211.0
#pos = nx.spring_layout(G)
#instead of spring, set the positions yourself
labelPosDict = {'R':[0.1,0.3], 'D04':[0.5,.9], 'D06':[.9,.18]}
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos=labelPosDict, edge_labels=labels)
plt.axvline(.1, alpha=0.1, color='green')
plt.axhline(.3, alpha=0.1, color='green')
#Create a dict of fixed node positions
nodePosDict = {'R':[0.1,0.3], 'D04':[0.5,.9], 'D06':[.9,.18]}
# Make the graph - add the pos and connectionstyle arguments
nx.draw(G, k=5,with_labels=True, pos=nodePosDict,
        node_size=1500, alpha=0.3, font_weight="bold", arrows=True,
       connectionstyle='arc3, rad = 0.1')
plt.axis('on')
plt.show()

By controlling the pos dict, you can now place things exactly where you want them, and they won't change each time (spring uses a random starting point by default, that's why the layout changes each time)

enter image description here

Related