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

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)

Related

Having a directed graph in pyhton (networkx), is it possible to create a subgraph according to a specific condition on the node attributes?

I have a twitter data set that i want to analyze,after creating a directed graph(the nodes are twitter users, and edge from a to b means a follows b)
how i created the graph :
I want to make a sub graph that contains only male users and edges between them, and another one containing only female users and edges between them.
thank you.
I am working on a similar problem, and I think there are two fitting stack answers:
Select nodes and edges form networkx graph with attributes
partition graph into sungraphs based on node's attribute NetworkX
The preliminary requirement is that you add attributes to your nodes and edges according to what you need to use later
Not sure if this is satisfactory, but maybe it'll help a little.
PS. If you've already solved it, paste your solution here so others can see :)

How to draw readable, preferably interactive, network graphs with python?

I'm trying to draw a graph of any network running my script. I use scapy to collect packets and would like to have a node per computer communicating, and an edge per connection.
The issue is I can't find a way to visualize the graph well enough on my screen. So far combining networkx with matlib.pyplot managed to bring the best results, but it still seems pretty random and chaotic, the tags are hard to read, nodes are on top of each other, etc'. It is also preferable to have the ability to interact with the graph - move nodes around, hover over nodes/edges to get extra info, perhaps zoom in or even cluster together nodes so that when you click on the cluster you can see which nodes compose the cluster.
Since analyzing the network data and adding nodes&edges to the graph will be tedious for you to read, I'm adding only the relevant part here (the part that actually shows the graph I built):
pos = nx.spring_layout(Graph, scale=2)
edge_labels = nx.get_edge_attributes(Graph, "Protocol")
nx.draw(Graph,pos, with_labels=True, node_size=600, font_size=8, font_weight='bold')
nx.draw_networkx_edge_labels(Graph, pos, edge_labels=edge_labels, font_size=8)
plt.show()
(I imported networks as nx and matplotlib.pyplot as plt)
I also tried graphviz, ploty and bokeh but couldn't really make them work and after troubleshooting on Google got the impression that anyway they won't fix my problem, and I also tried adjustText - but I could not manage to fit it in my code in any way (can't find how to get the text attribute of my graph) and Holoviews - but it refuses to show an image no matter what I try (even if I copy and paste examples from their site - either python says that '%opts...' is invalid syntax, or if I try changing options any other way the code just runs until it ends and doesn't show anything on the screen.
This is what the graph looks like:
I'm finding a lot of partial solutions online so none of them work, does anybody has a comprehensive solution?
Drawing heavy graphs with plt can be a bit problematic, the problem here is not only with the data, it is also a problem for a human eye to get a lot of information in one look.
My suggestion is to use a more advanced graph visualization library, for example, ipycytoscape. you can define also styles and more features with it that will match your demands
from ipycytoscape import CytoscapeWidget
graph_draw = ipycytoscape.CytoscapeWidget()
graph_draw.graph.add_graph_from_networkx(nx_graph, directed=True)
In addition, if you will use CytoscapeWidget you can interact with the graph and match the focus of the view to the part in the graph that interests you the most.
You can tune the hyper-parameters (k and iterations) of the nx.spring_layout to arrange the nodes. Once you tune the parameters, the connected nodes will be close to each other, and not-contacted nodes will maintain a maximum possible distance.
pos = nx.spring_layout(G,k=0.1, iterations=20)

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.

Graphviz: how to insert two new linked nodes and minimize edge crossings?

I have the following graph :
As you can see, there are two natural clusters. I would like to figure out a way to separate these clusters into two graphs.
The key step, of course, is to compute the right split. I would like to insert two nodes n1 & n2, link them e(n1, n2), and move them around, minimizing the number of edge crossings (of course fixing all nodes/edges exactly where they are).
Can anyone offer any help here? I don't think graphviz has anything that enables me to do it.
I think you mingle two different tasks here: the one is Analysis of a graph, the other one is Visualization of the same.
Graphviz, as the name suggests, is a tool for visualization of graphs. Visualization can take many forms, typically one tries to "make it look good" by having those nodes close to each other that are connected, thus reducing the visual edge lengths. One can utilize some spring- or gravitational model to calculate optimal positions for all nodes. Other options include circular- or shell-layouts.
A certain visualization should not be the basis for the analysis of a graph. Graph properties, like average shortest path length or clustering coefficient, are independent of any visualization.
You say you want to "minimize the number of edge crossings". The number of edge crossings is a property of your visualization, not of your graph! It probably changes each time you let graphviz calculate the layout, even if the graph is unchanged. Who says that 2d is the only possible representation of your graph? Add just one dimension, and you won't have any edge crossing.
I'd recommend to concentrate on graph analysis. I don't know if you're aware of NetworkX. They have dozens of Algorithms to analyze your graph. Maybe the clustering and clique sections are of interest to you.

datacursormode for networkx

I have plotted a large graph with networkx and want to see the names of each vertex, unfortunately there are too many to read easily. Looking around I have found implementations of datacursormode in matplotlib but have been unable to make them work as networkx.draw does not return objects. Here's the original question
Is there a matplotlib equivalent of MATLAB's datacursormode?
Many Thanks
edit: I can get it to work by editting http://www.scipy.org/Cookbook/Matplotlib/Interactive_Plotting but would ideally have some idea which vertex I selected, so that I can change the colour of adjacent edges.
You can usually retrieve the artist in question using the following command in the callback function:
thisline = event.artist
And from there check things like labels (thisline.get_label()) or whatever other artist properties are of interest to you.
This, however, assumes that have some labeling system in place for the vertices already, or another way of determining which virtex is which. If you don't, that's another story altogether.

Categories