Bipartite graph in NetworkX for LARGE amount of nodes - python

I am trying to create bipartite of certain nodes, for small numbers it looks perfectly fine:
Image for around 30 nodes
Unfortunately, this isn't the case for more nodes like this one:
Image for more nodes
My code for determining the position of each node looks something like this:
pos = {}
pos[SOURCE_STRING] = (0, width/2)
row = 0
for arr in left_side.keys():
pos[str(arr).replace(" ","")]=(NODE_SIZE, row)
row += NODE_SIZE
row = 0
for arr in right_side.keys():
pos[str(arr).replace(" ","")]=(2*NODE_SIZE,row)
row += NODE_SIZE
pos[SINK_STRING] = (3*NODE_SIZE, width/2)
return pos
And then I feed it to the DiGraph class:
G = nx.DiGraph()
G.add_nodes_from(nodes)
G.add_edges_from(edges, len=1)
nx.draw(G, pos=pos ,node_shape = "s", with_labels = True,node_size=NODE_SIZE)
This doesn't make much sense since they should be in the same distance from each other since NODE_SIZE is constant it doesn't change for the rest of the program.
Following this thread:
Bipartite graph in NetworkX
Didn't help me either.
Can something be done about this?
Edit(Following Paul Brodersen Advice using netGraph:
Used this documentation: netgraph doc
And still got somewhat same results, such as:
netgraph try
Using edges and different positions, also played with node size, with no success.
Code:
netgraph.Graph(edges, node_layout='bipartite', node_labels=True)
plt.show()

In your netgraph call, you are not changing the node size.
My suggestion with 30 nodes:
import numpy as np
import matplotlib.pyplot as plt
from netgraph import Graph
edges = np.vstack([np.random.randint(0, 15, 60),
np.random.randint(16, 30, 60)]).T
Graph(edges, node_layout='bipartite', node_size=0.5, node_labels=True, node_label_offset=0.1, edge_width=0.1)
plt.show()
With 100 nodes:
import numpy as np
import matplotlib.pyplot as plt
from netgraph import Graph
edges = np.vstack([np.random.randint(0, 50, 200),
np.random.randint(51, 100, 200)]).T
Graph(edges, node_layout='bipartite', node_size=0.5, node_labels=True, node_label_offset=0.1, edge_width=0.1)
plt.show()

Related

How to add edge weights to plot output in Bokeh?

I wonder how I can add the edge weights to my Bokeh plot (from NetworkX), preferably for edge_renderer.hover_glyph, like in this picture:
A possible answer for this problem is using nx.get_edge_attributes and pass the values to draw_networkx_edge_labels as the labels for the edges.
Here's the so awaited code:
pos=nx.spring_layout(G)
nx.draw_networkx(G, pos)
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)
Here's a full working example:
import networkx as nx
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(4,4))
G = nx.Graph()
G.add_node('A', pos="1,3!", demand=-10)
G.add_node('B', pos="3,5!")
G.add_node('C', pos="3,1!")
G.add_node('D', pos="4,3!")
G.add_node('E', pos="5,5!")
G.add_node('F', pos="5,1!")
G.add_node('G', pos="7,3!", demand=10)
G.add_edge('A','B',weight=20,capacity=20,label='(20,20)')
G.add_edge('A','C',weight=7,capacity=15,label='(7,15)')
G.add_edge('B','E',weight=16,capacity=21,label='(16,21)')
G.add_edge('B','D',weight=4,capacity=4,label='(4,4)')
G.add_edge('C','F',weight=3,capacity=9,label='(3,9)')
G.add_edge('C','D',weight=4,capacity=4,label='(4,4)')
G.add_edge('D','E',weight=2,capacity=2,label='(2,2)')
G.add_edge('D','F',weight=6,capacity=10,label='(6,10)')
G.add_edge('E','G',weight=18,capacity=24,label='(18,24)')
G.add_edge('F','G',weight=9,capacity=10,label='(9,10)')
pos=nx.spring_layout(G)
nx.draw_networkx(G, pos)
labels = nx.get_edge_attributes(G,'weight')
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)

Networkx viz - How do I sort nodes before plotting them in circular layout?

I am trying to create timetables or cardioid graph using network in python this is my code
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
n = 10
for i in range(1,n):
if i*2 < n:
G.add_node(i, weight=i)
G.add_node(i*2, weight=i*2)
G.add_edge(i, i*2)
else:
G.add_node(i, weight=i)
G.add_node(i*2-n, weight=i*2-n)
G.add_edge(i,i*2 - n)
plt.figure(figsize=(10,6))
nx.draw_networkx(G, pos=nx.circular_layout(G), node_size=1000)
But then I am getting something like this
enter image description here
Whereas I want nodes to be in a a sorted manner like 0,1,2... in circular format, how do I achieve that?
You can achieve it by using
nx.draw_networkx(G, pos=nx.circular_layout(sorted(G.nodes()), node_size=1000)
to get the nodes sorted in an anticlockwise manner.
Otherwise, for a clockwise ordering you can use
nx.draw_networkx(G, pos=nx.circular_layout(sorted(G.nodes(), reverse=True)), node_size=1000)
Example:

how can I visual a dense graph obviously in networkx python package?

I have a large, dense directed graph in python, made with the NetworkX package. How can I improve the clarity of the graph image?
The following image shows my graph.
I can recommend you several ways to improve your graph visualization depending on its size.
If you want to visualize a large graph (>1000 nodes), you can read some tricks in my another answer. In your case I recommend you to import the graph to a large vector picture:
import networkx as nx
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(40, 40))
G = nx.fast_gnp_random_graph(300, 0.02, seed=1337)
nx.draw(G, node_size=30)
plt.axis('equal')
plt.show()
fig.savefig('waka.svg')
If you have relatively small graph (<1000 nodes), you can play with graph layouts.
The most suitable layout for your kind of graph is the default spring_layout. It has k argument that set the optimal distance between nodes. Here is the example:
Default k value
import networkx as nx
import random
random.seed(1234)
G = nx.fast_gnp_random_graph(30, 0.4, seed=1337)
for i in range(20):
G.add_edge(i + 40, random.randint(1, 30))
G.add_edge(i + 40, random.randint(1, 30))
pos = nx.spring_layout(G, seed=4321)
nx.draw(G, pos=pos, node_size=30, node_color='red')
Enlarged k value
import networkx as nx
import random
random.seed(1234)
G = nx.fast_gnp_random_graph(30, 0.4, seed=1337)
for i in range(20):
G.add_edge(i + 40, random.randint(1, 30))
G.add_edge(i + 40, random.randint(1, 30))
pos = nx.spring_layout(G, seed=4321, k=2)
nx.draw(G, pos=pos, node_size=30, node_color='red')
It is less readable if you need analyse edges with high precision, but it is better if you are care more about nodes.

Graphviz: avoid overlapping edges and nodes

I know it's a recurrent question but I can't find a working answer in my case.
I have a graph with 365 nodes to plot correctly.
For now, the result is almost satisfying, but not perfect. As you can see, some edges cross each other, and some nodes overlap. I would like to avoid that, and I'm pretty sure it's possible, there is a lot of free space available for a better organization. I use the graphviz_layout function with NetworkX. Would you have any idea ?
Here is a working example:
import networkx as nx
import matplotlib.pyplot as plt
import re
import pygraphviz
from networkx.drawing.nx_agraph import graphviz_layout
G = nx.Graph()
G.add_node(1)
inp = "BDDDDDDDDDCCDDCh14CCCh13Ch10Ce24CCh9DCCCCh28CCh8DDDDDDDCCCCCh43Ch42CCCCh41DDDh59Ch58CCCh57CCh40CCDCCh72CCCCCCh39CDDCCh85Ch84h38Ch37DDDCh96Ch95h94CCCh7CDDDDDCDCDh115CDCCh118CCh113Dh125Ch111CDe131CCCh130h110Ch109DDCCCCh140CCh139CCCCh108CCCh107DDh159CCCh158CCCh6DDDDDDCh174CCCh173DCDCDDCCCh186CCh185CCh183CCh181Ch172Ch171DDDCCCh206CCh205CCh204Ch170CCCCh169CCCh5DDDCCCh230DDe237CCCh236CCCh235Ch229CCCCh228CCCCCCCh4CCCh3DDDCDDCCh270Ch269DDh277h276CCh267CCCh266DDCCh288CCCh287CCCCCh265DCCCCh302CCh2CCCCCh1DCCDDDh322Ch321DDCe329CCCCCCCCh327CCh326CCCCCh320CCDCCCh350CCCh317DCe361Ch359Ch"
chains = re.findall("([a-zA-Z]+)", inp)
bp = [int(value) for value in re.findall("([0-9]+)", inp)]
while G.number_of_nodes() < len(chains[0]):
G.add_node(G.number_of_nodes() + 1)
G.add_edge(G.number_of_nodes(), G.number_of_nodes() - 1)
for number, sequence in zip(bp, chains[1:]):
G.add_node(G.number_of_nodes() + 1)
G.add_edge(number, G.number_of_nodes())
for res in sequence[:-1]:
G.add_node(G.number_of_nodes() + 1)
G.add_edge(G.number_of_nodes(), G.number_of_nodes() - 1)
pos = nx.nx_agraph.graphviz_layout(G)
fig = plt.figure(1)
nx.draw(G, pos)
fig.set_size_inches(50, 50)
plt.savefig('tree.png', bbox_inches='tight')

how do I label the nodes in a network graph? by importing networkx in python?

This is my code, I am plotting a randomly generated graph containing 8 nodes
import networkx as nx
import matplotlib.pyplot as plt
import random
from sets import Set
from array import array
def draw_graph(graph):
# extract nodes from graph
nodes = set([n1 for n1, n2 in graph] + [n2 for n1, n2 in graph])
# create networkx graph
G=nx.Graph()
# add nodes
for node in nodes:
G.add_node(node)
# add edges
for edge in graph:
G.add_edge(edge[0], edge[1])
# draw graph
pos = nx.shell_layout(G)
nx.draw(G, pos)
# show graph
plt.show()
##draw example
zero=random.choice([1,4])
one=random.choice([2,3])
two=random.choice([1,7])
three=random.choice([1,5])
four=random.choice([0,6])
five=random.choice([3,7])
seven=random.choice([2,5])
graph = [(0,zero),(1,one),(2,two),(3,three),(4,four),(5,five),(6,4),(7,seven)]
draw_graph(graph)
now I have to label each node and I has to know positions of each node.. How to do it?? thanks in advance..

Categories

Resources