Dynamic node sizes in pyvis - python

I'm wanting to make nodes different sizes depending on the number of connections. However, it seems like this functionality isn't present in pyvis? Maybe I'm missing something or it might not be supported entirely.
Here's my sample code:
import networkx as nx
import matplotlib.pyplot as plt
from pyvis.physics import Physics
from pyvis.network import Network
G = nx.Graph()
G.add_edges_from([(1,2), (2,3), (2,4), (3,4)])
d = dict(G.degree)
print(d.keys())
print([v * 100 for v in d.values()])
nx.draw(G, nodelist=d.keys(), node_size=[v * 100 for v in d.values()])
plt.show()
G2 = Network(height="1500px", width="75%",bgcolor="#222222",font_color="white",directed=True)
G2.from_nx(G)
G2.show("network_map.html")

You can do that in a few lines by using the set_node_attributes function from networkx. It allows you to add/modify node attributes (see more info here). See below where I used it to change the size of the nodes:
import networkx as nx
import matplotlib.pyplot as plt
from pyvis.physics import Physics
from pyvis.network import Network
G = nx.Graph()
G.add_edges_from([(1,2), (2,3), (2,4), (3,4)])
scale=10 # Scaling the size of the nodes by 10*degree
d = dict(G.degree)
#Updating dict
d.update((x, scale*y) for x, y in d.items())
#Setting up size attribute
nx.set_node_attributes(G,d,'size')
G2 = Network(height="1500px", width="75%",bgcolor="#222222",font_color="white",directed=True)
G2.from_nx(G)
G2.show("network_map.html")
And the output gives:

Related

Bipartite graph in NetworkX for LARGE amount of nodes

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()

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:

Python networkx - How to draw graph with labels

from graphviz import *
import networkx as nx
from networkx import *
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_node(1)
G.add_node(2)
G.add_edge(1,2)
myLabels = {1: 'node1', 2: 'node2'}
nx.set_node_attributes(G, myLabels, 'label')
nx.draw(G,with_labels=True)
So current I use the latest networkx. When I use nx.draw(G, with_values=True), it uses the vertex indexes instead of labels.
How can I fix this? Thank you.
Change this command: nx.draw(G,with_labels=True) to nx.draw(G,with_labels=True, labels = myLabels)

Save a graph in the graph6 format in Python using networkx

I try to save a graph in graph6 format in Python with networkx. The obvious way does not seem to work:
import networkx as nx
g = nx.Graph()
g.add_edge('1','2')
nx.write_graph6(g,"anedge.g6")
g1 = nx.read_graph6("anedge.g6")
import matplotlib.pyplot as plt
nx.draw(g1)
plt.savefig("anedge.pdf")
This makes a pdf file showing a graph with two isolated vertices instead of two connected vertices.
Using g.add_edge(0, 1) instead of g.add_edge('1','2') it should work:
import networkx as nx
import matplotlib.pyplot as plt
g = nx.Graph()
g.add_edge(0, 1)
nx.write_graph6(g, 'anedge.g6')
g1 = nx.read_graph6('anedge.g6')
nx.draw(g1)
plt.savefig("anedge.pdf")
This is actually exposing a bug in the networkx graph6 generator when the nodes are not consecutively ordered from zero. Bug fix is here https://github.com/networkx/networkx/pull/2739

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')

Categories

Resources