Home > database >  How can I draw graphs network using networkx and asking if there should be connection between a pare
How can I draw graphs network using networkx and asking if there should be connection between a pare

Time:10-14

I am completely new on making network graphs in Python. I came to learn that networkx library can be used to plot network graphs in Python.

I have 11 nodes. Node1, Node2, ..., Node11. I want to plot them in four different levels. Node1 is in level 1. Node2 and Node3 are in level 2. Node4 to Node7 are in level3, and Node8 to Node11 are in level 4.

I have created a very simple basic network graph between level 1 and 2 using

# Build a dataframe with 4 connections
df = pd.DataFrame({ 'from':['Node1',"Node1"], 'to':["Node2","Node3"]})
 
# Build your graph
G=nx.from_pandas_edgelist(df, 'from', 'to')
 
# Plot it
nx.draw(G, arrows = True, with_labels = True)
plt.show()

And it looks as follows:enter image description here I want to plot Node2 and Node3 in the same direction towards right of Node1 above and below it respectively. Is it also possible to get a rectangle instead of a circle in the node, and is it also possible to display the labels outside of the node?

To plot between level 2 and level3, I want to ask the user if there is edgelink between each of Node2 and Node3, with each of Node4, Node5, Node6 and Node7. Also, I want to ask the user if there is edge link between each node in level 3 and level 4 respectively?

It should look something as shown below and the connections between level 2 and level 3, and level 3 and level 4 should be based on user input. What would be the suitable way to obtain this network graph plot? Is there any other libraries better suited for this?enter image description here

CodePudding user response:

Based on other question on Stackoverflow: enter image description here


Based on other answer on Stackoverflow - you can use node_shape to change shape like in matplotlib. I found only square - node_shape='s' - and using node_size=1000 I could change size for all squares or use list/tuple node_size=(1000, 1000, ...) to change size to every node separatelly

nx.draw(G, pos=positions, arrows=True, with_labels=True, node_shape='s', node_size=1000)

Result:

enter image description here


Based on documentation I found that you can draw separatelly nodes, labels, edges so you can use different positions for labes and set them above node.

nodes_positions = {
    'Node1': (0, 0),
    'Node2': (1, 1),
    'Node3': (1, -1),
    'Node4': (2, 2),
    'Node5': (2, 0),
}    

labels_positions = {
    'Node1': (0, 0.3),
    'Node2': (1, 1.3),
    'Node3': (1, -0.7),
    'Node4': (2, 2.3),
    'Node5': (2, 0.3),
}    

nx.draw_networkx_nodes(G, pos=nodes_positions, node_shape='s', node_size=1000)
nx.draw_networkx_labels(G, pos=labels_positions)
nx.draw_networkx_edges(G, pos=nodes_positions)

Result:

enter image description here


Doc:


EDIT:

Full example code for last image

import pandas as pd
import networkx as nx
from matplotlib import pyplot as plt

#df = pd.DataFrame({
#    'from': ['Node1', 'Node1', 'Node2', 'Node2'],
#    'to': ['Node2', 'Node3', 'Node4', 'Node5']
#})

df = pd.DataFrame([
    # pairs (from, to)
    ('Node1', 'Node2'),
    ('Node1', 'Node3'),
    ('Node2', 'Node4'),
    ('Node2', 'Node5'),
], columns=['from', 'to'])
 
G = nx.from_pandas_edgelist(df, 'from', 'to')
 
nodes_positions = {
    'Node1': (0, 0),
    'Node2': (1, 1),
    'Node3': (1, -1),
    'Node4': (2, 2),
    'Node5': (2, 0),
}    

labels_positions = {
    'Node1': (0, 0.3),
    'Node2': (1, 1.3),
    'Node3': (1, -0.7),
    'Node4': (2, 2.3),
    'Node5': (2, 0.3),
}    

#nx.draw(G, pos=positions, arrows=True, with_labels=True, node_shape='s', node_size=1000)
nx.draw_networkx_nodes(G, pos=nodes_positions, node_shape='s', node_size=1000)
nx.draw_networkx_labels(G, pos=labels_positions)
nx.draw_networkx_edges(G, pos=nodes_positions)

plt.show()

CodePudding user response:

furas has answered first half of my question. For the second part, I created two lists using for-loop to determine if there is link between two specific nodes and updated the lists accordingly. Using the list, I created a dataframe containing From and To columns, that reflect the linkage from any parent to child node(s).

a = ["Node1","Node1"]
b = ["Node2","Node3"]

#Ask if you want link between nodes 2 and 3, with each of node 4 to 7
for i in range(2,4):
    for j in range(4,8):
        edge = input(f"Edge between {i} and {j}?")
        if edge == "Yes":
            a.append(f"Node{i}")
            b.append(f"Node{j}")

#Ask if you want link between nodes 4 and 7, with each of node 5 to 8
for i in range(4,8):
    for j in range(8,12):
        edge = input(f"Edge between {i} and {j}?")
        if edge == "Yes":
            a.append(f"Node{i}")
            b.append(f"Node{j}")

#Create a dataframe using the lists a and b
df = pd.DataFrame([])
df["From"] = a
df["To"] = b
df
  • Related