1

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 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

5 Comments

Wow this seems awesome! I can see what you mean now by having to place the nodes myself. However this was only a thought I had as to have the nodes be placed correctly. The end goal wold be having the nodes be placed accordingly to how far they are away from each other via. the edge weights. Do you know how this would be done?
This answer seems to be on target for what you need to do, which is determine points based on distances. stackoverflow.com/questions/10963054/…
I'll have a look. Have a great day, thank you!
BTW. The nx.draw function complains about the 'k' variable. Deleting this makes your code run :)
Ah - I should have listed my versions - networkx: 2.4, matplotlib: 3.2.1

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.