Visualize a networkx graph in plotly dash using a dataframe - python

I have a pandas dataframe that contains 3 columns , ['source' , 'target', 'weight'].
I have created a networkx graph successfully and plotted it in the browser. The networkx graph was created using the following line of code:
Graph = nx.from_pandas_edgelist(rules,source='source',target='target').
Using the networkx library, it was easy to create the graph using only the above line of code, and setting the nodes labels, arrows that shows the sense from source to destination etc...
I want to do this using plotly dash to have an interactive plot, however, in the examples I have seen in plotly dash networkx, they always have to declare the nodes and edges manually, which will require to have a for loop over the dataframe to pass all the entries of the dataframe. In my case, I have a pretty large dataframe which will be a problem.
My question is that, is there a way that I am missing, to create the graph using dash in a simple way without the need to declare the edges and the nodes manually? a way similar to that line of code?
Graph = nx.from_pandas_edgelist(rules,source='source',target='target').
and if there is a way, can I access the nodes by their ids? and how to insert nodes labels in the graph.
Thank you in advance.
I have tries visdcc and cytoscape libraries using plotly dash. In visdcc I used a loop which took a lot of time to pass through the dataframe entries. And in cytoscape, it needs to create the nodes and edges manually, which I do not want to do, my question is, if there is a way to create the graph automatically using the dataframe as networkx and the draw option do.

Yes, it is possible to use a dataframe to create a network graph with Networkx and then render this network graph in Dash-Cytoscape (you don't have to enter nodes and edges manually). In the question I asked yesterday (here), you can find a code example to achieve this (my question was about something more specific).

Related

Networkx like nodes arrangement in Pyvis

I am currently using streamlit to develop an app which uses Pyvis to render some network graphs. Streamlit supports the use of Pyvis to render the plot, but not Networkx to my knowledge. Networkx graphs can though be transformed in Pyvis Graphs through the pyvis.network.from_nx() function. My problem is that the graphs are a little messy (i have about 100 nodes on the screen with very variable connectivity). Now i know Networkx has some methods to arrange the nodes neatly as in this example:
https://linuxtut.com/en/7c550010f5915ae4acdc/
But I don't know how to do that with Pyvis. I tried to read Pyvis documentation, but didn't find much on the arrangement of the nodes. Does anyone know any Pyvis native solution to arrange large number of nodes neatly?

Packages that work with networkx that can handle clickable nodes

I'm looking to try and visualize data using networkx as a network graph. My data looks great, but i'm wanting to add on hover and on click events to display additional information.
For example, there might be a node called "New York", when clicked will display a small table to the side of the canvas that gives information like how many cities, current population, etc.
I'm currently using pyviz with networkx. That seems to be really straightforward as far as creating the graph, but not so much on the kind of user interaction i'm looking for.
I also tried bokeh and plotly, but on the on click and hover functions while work, isn't very straightforward to implement with networkx. Here's a picture of what my graph looks like. My goal is to show relationships between systems.
pyvis graph
I maintain a python library for network visualisations called netgraph, which works nicely with networkx or igraph Graph objects. I thought this was a neat idea for a feature, so I just implemented a bare bones version on the dev branch.
Installation via pip:
pip install https://github.com/paulbrodersen/netgraph/archive/dev.zip
Code to reproduce the example above:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import networkx as nx
from netgraph import InteractiveGraph
g = nx.cubical_graph()
tables = dict()
for node in g.nodes:
data = np.round(np.random.rand(3,2), decimals=2)
table = pd.DataFrame(data, index=['Lorem', 'ipsum', 'dolor'], columns=['sit', 'amet'])
tables[node] = table
for edge in g.edges:
data = np.round(np.random.rand(4,1), decimals=2)
table = pd.DataFrame(data, index=['consectetur', 'adipiscing', 'elit', 'Mauris'], columns=['sed'])
tables[edge] = table
fig, ax = plt.subplots(figsize=(12,5))
fig.subplots_adjust(right=0.6) # make space for table on the right
bbox = [1.5, 0.1, 0.5, 0.8] # position of the table in axes coordinates
instance = InteractiveGraph(g, node_labels=True, tables=tables, table_kwargs=dict(edges='horizontal', fontsize=16, bbox=bbox), ax=ax)
plt.show()
Take a look at the kglab project which is an open source abstraction layer in Python that integrates both NetworkX and PyVis, along with other graph related libraries in Python. It was built for this kind of use case.
There's a class kglab.KnowledgeGraph which has transforms and inverse transforms to work these other libraries:
NetworkX examples https://derwen.ai/docs/kgl/ex6_0/
PyVis examples https://derwen.ai/docs/kgl/ex3_0/
For instance, you could:
build a graph using a KnowledgeGraph object
transform out to run NetworkX graph algorithms
use an inverse transform to populate calculated attributes on the main graph object
transform out to load and run a PyVis interactive session, which in turn can have clickable components
We've got Jupyter notebooks on the GH repo showing each of these steps. plus a developer community where other people can help for a specific use case (create a GH issue)
There is VisDCC, which requires Dash (a kind of data-science server thing).
The end result is a web server serving an HTML canvas that you can insert in a web page, for instance. (This is actually inherited from Vis.js)
VisDCC has almost no documentation but it works (I'm using it) and the usage follows that of Dash which is well-documented. You need to learn to use Dash's #callback format to write the code.
So I guess it's a good enough solution :)

Does graph-tool have a way of projecting bipartite graphs?

I'm trying to project a bipartite graph into two single mode graphs.
I'm want to analyze a bipartite graph using the dual projection approach. I have been using NetworkX, but I wanted to try graph-tool since it claims to be more efficient. There is a chance that my graph will get very big very quickly, so I want to use the most efficient method/package. The package graph-tool claims to be more efficient, and I would like to try it out, but I cannot find a way to project a bipartite graph using it. Does anybody know if this is possible using graph-tool? The only information I found was the creator asking somebody who asked a similar question to create a ticket so that he/they can start working on it, but it's from 2014.
I had the same problem and got a solution working. I have got it working on graphs up to 5 million nodes.
It follows three main steps:
use the is_bipartite function to generate a boolean array of which set each vertex belongs to.
loop over the set to be removed adding edges between all combinations of neighbours.
use the GraphView to generate a new graph by only keep the nodes of the set of interest.
g = gt.lattice([5,5])
is_biparitite, part = gt.is_bipartite(g, partition=True)
gt.graph_draw(g, vertex_fill_color=part) # to view the full graph coloured by set
from itertools import combinations
g_temp = g.copy() # this is a deepcopy
for v, bipartite_label in enumerate(part):
if bipartite_label == 0:
neighbours = list(g.vertex(v).all_neighbours())
for s, t in combinations(neighbours, 2):
g_temp.add_edge(s, t)
g_projected = gt.Graph(gt.GraphView(g_temp, vfilt=part.a==1), prune=True)
gt.graph_draw(g_projected)

Python 2.7 NetworkX (Make it interactive)

I am new to NetworkX. Right now, I manage to connect all the nodes to this particular node. What I want to do next it to make it interactive e.g. able to make each of the node move by dragging using cursor. I know I have to make use of matplotlib, but I am not sure how to use it. Can anyone help me?
My codes are:
import matplotlib.pyplot as plt
import networkx as nx
import itertools
d = [name of nodes]
f = [number per nodes]
for i in d:
G.add_edge('"' + i + '"',b)
pos=nx.fruchterman_reingold_layout(G, k=0.5, iterations=5)
nx.draw_networkx_nodes(G,pos,node_size=130, node_color="white")
nx.draw_networkx_edges(G,pos, width=0.2,alpha=1,edge_color='black')
nx.draw_networkx_labels(G,pos,font_size=7,font_family='sans-serif')
for i,j in itertools.izip(d,f):
nx.draw_networkx_edge_labels(G,pos, {('"' + i + '"',b):j}, font_size=7, label_pos= 0.80)
plt.axis('off')
plt.show()
It seems hard to do with matplotlib (it is not really been designed for that). Networkx drawing module is pretty poor it mostly uses a custom scatter plot for nodes, etc.
I suggest another solution:
Export your graph to JSON or GEXF and use a Javascript graph drawing library to make your graph interactive such as: SigmaJs, or VivaGraphJs.
You find an example of a real graph created with NetworkX embedded on a webpage on my blog. Nodes are static in this example but clicking on a node highlights its neighbors.
Official examples for the proposed interactive graph drawing libraries:
List of examples using sigma.js.
Tutorial for VivaGraphJs.
Matplotlib was designed more for static graphs and charts.
However once the NetworkX graph is exported to GEXF format there is a tool which will allow you to select areas based on position or critera in order to move it around. The tool is called Gephi. You can play with the layout to get started or go as deep as data scientists like to get.

How to efficiently animate a Graphviz graph?

I would like to animate a Graphviz generated graph, changing the node labels and the node and edge colors.
I was creating the graphs using this Python interface for Graphviz. The only way to do that seems to be to create every image independently (although the changes between frames would be very small) and join all the images into an animation, as explained here.
Is there a more efficient way to create the animation, avoiding the creation of all these images independently?
There is also d3-graphviz, which takes a full dot graph description per animation step, converts it into an SVG, and then uses JavaScript to convert one graph into the other, and to inject animation.
You can see an example here.
There is a python package (GraphvizAnim) to do so.
Being in alpha only, but non the less looking quite decent.

Categories