Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Improving Python NetworkX graph layout

I am having some problems in visualizing the graphs created with python-networkx, I want to able to reduce clutter and regulate the distance between the nodes (I have also tried spring_layout, it just lays out the nodes in an elliptical fashion). Please advise. enter image description here

Parts of code:

nx.draw_networkx_edges(G, pos, edgelist=predges, edge_color='red', arrows=True) nx.draw_networkx_edges(G, pos, edgelist=black_edges, arrows=False, style='dashed') # label fonts nx.draw_networkx_labels(G,pos,font_size=7,font_family='sans-serif') nx.draw_networkx_edge_labels(G,pos,q_list,label_pos=0.3) 
like image 304
Sayan Avatar asked Feb 24 '14 03:02

Sayan


People also ask

Can NetworkX handle large graphs?

NX is certainly capable of handling graphs that large, however, performance will largely be a function of your hardware setup. Aric will likely give a better answer, but NX loads graphs into memory at once, so in the ranges your are describing you will need a substantial amount of free memory for it to work.

Which is better iGraph or NetworkX?

NetworkX is pure Python, well documented and handles changes to the network gracefully. iGraph is more performant in terms of speed and ram usage but less flexible for dynamic networks. iGraph is a C library with very smart indexing and storage approaches so you can load pretty large graphs in ram.

Is NetworkX scalable?

The fact that networkX is mostly written in python does not mean that it is not scalable, nor claims perfection. There is always a trade-off. If you throw more money on your "machines", you'll have as much scalability as you want plus the benefits of using a pythonic graph library.


2 Answers

In networkx, it's worth checking out the graph drawing algorithms provided by graphviz via nx.graphviz_layout.

I've had good success with neato but the other possible inputs are

  • dot - "hierarchical" or layered drawings of directed graphs. This is the default tool to use if edges have directionality.

  • neato - "spring model'' layouts. This is the default tool to use if the graph is not too large (about 100 nodes) and you don't know anything else about it. Neato attempts to minimize a global energy function, which is equivalent to statistical multi-dimensional scaling.

  • fdp - "spring model'' layouts similar to those of neato, but does this by reducing forces rather than working with energy.

  • sfdp - multiscale version of fdp for the layout of large graphs.

  • twopi - radial layouts, after Graham Wills 97. Nodes are placed on concentric circles depending their distance from a given root node.

  • circo - circular layout, after Six and Tollis 99, Kauffman and Wiese 02. This is suitable for certain diagrams of multiple cyclic structures, such as certain telecommunications networks.

In general, graph drawing is a hard problem. If these algorithms are not sufficient, you'll have to write your own or have networkx draw parts individually.

like image 178
Hooked Avatar answered Oct 01 '22 06:10

Hooked


I found this to be useful for quickly visualizing interaction data (here, genes) sourced as a CSV file.

Data file [a.csv]

APC,TP73 BARD1,BRCA1 BARD1,ESR1 BARD1,KRAS2 BARD1,SLC22A18 BARD1,TP53 BRCA1,BRCA2 BRCA1,CHEK2 BRCA1,MLH1 BRCA1,PHB BRCA2,CHEK2 BRCA2,TP53 CASP8,ESR1 CASP8,KRAS2 CASP8,PIK3CA CASP8,SLC22A18 CDK2,CDKN1A CHEK2,CDK2 ESR1,BRCA1 ESR1,KRAS2 ESR1,PPM1D ESR1,SLC22A18 KRAS2,BRCA1 MLH1,CHEK2 MLH1,PMS2 PIK3CA,BRCA1 PIK3CA,ESR1 PIK3CA,RB1CC1 PIK3CA,SLC22A18 PMS2,TP53 PTEN,BRCA1 PTEN,MLH3 RAD51,BRCA1 RB1CC1,SLC22A18 SLC22A18,BRCA1 TP53,PTEN 

Python 3.7 venv

import networkx as nx import matplotlib.pyplot as plt G = nx.read_edgelist("a.csv", delimiter=",")  G.edges() '''   [('CDKN1A', 'CDK2'), ('MLH3', 'PTEN'), ('TP73', 'APC'), ('CHEK2', 'MLH1'),     ('CHEK2', 'BRCA2'), ('CHEK2', 'CDK2'), ('CHEK2', 'BRCA1'), ('BRCA2', 'TP53'),     ('BRCA2', 'BRCA1'), ('KRAS2', 'CASP8'), ('KRAS2', 'ESR1'), ('KRAS2', 'BRCA1'),     ('KRAS2', 'BARD1'), ('PPM1D', 'ESR1'), ('BRCA1', 'PHB'), ('BRCA1', 'ESR1'),     ('BRCA1', 'PIK3CA'), ('BRCA1', 'PTEN'), ('BRCA1', 'MLH1'), ('BRCA1', 'SLC22A18'),     ('BRCA1', 'BARD1'), ('BRCA1', 'RAD51'), ('CASP8', 'ESR1'), ('CASP8', 'SLC22A18'),     ('CASP8', 'PIK3CA'), ('TP53', 'PMS2'), ('TP53', 'PTEN'), ('TP53', 'BARD1'),     ('PMS2', 'MLH1'), ('PIK3CA', 'SLC22A18'), ('PIK3CA', 'ESR1'), ('PIK3CA', 'RB1CC1'),     ('SLC22A18', 'ESR1'), ('SLC22A18', 'RB1CC1'), ('SLC22A18', 'BARD1'),      ('BARD1', 'ESR1')] ''' G.number_of_edges() # 36  G.nodes() '''   ['CDKN1A', 'MLH3', 'TP73', 'CHEK2', 'BRCA2', 'KRAS2', 'CDK2', 'PPM1D', 'BRCA1',     'CASP8', 'TP53', 'PMS2', 'RAD51', 'PIK3CA', 'MLH1', 'SLC22A18', 'BARD1',     'PHB', 'APC', 'ESR1', 'RB1CC1', 'PTEN'] ''' G.number_of_nodes() # 22 

UPDATE

This used to work (2018-03), but now (2019-12) gives a pygraphviz import error:

from networkx.drawing.nx_agraph import graphviz_layout  nx.draw(G, pos = graphviz_layout(G), node_size=1200, node_color='lightblue', \     linewidths=0.25, font_size=10, font_weight='bold', with_labels=True)      Traceback (most recent call last):     ...     ImportError: libpython3.7m.so.1.0: cannot open shared object file:       No such file or directory     During handling of the above exception, another exception occurred:       Traceback (most recent call last):     ...     ImportError: ('requires pygraphviz ', 'http://pygraphviz.github.io/') 

SOLUTION

Outside Python (at the venv terminal prompt: $) install pydot.

pip install pydot 

Back in Python run the following code.

import warnings warnings.filterwarnings("ignore", category=UserWarning)  import networkx as nx import matplotlib.pyplot as plt  G = nx.read_edgelist("a.csv", delimiter=",") # For a DiGraph() [directed edges; not shown]: #   G = nx.read_edgelist("a.csv", delimiter=",", create_using=nx.DiGraph)  nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), node_size=1200, \     node_color='lightblue', linewidths=0.25, font_size=10, \     font_weight='bold', with_labels=True)  plt.show()    ## plot1.png attached 

The main change was to replace

nx.draw(G, pos = graphviz_layout(G), ...) 

with

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), ...) 

References

Remove matplotlib depreciation warning from showing

What could cause NetworkX & PyGraphViz to work fine alone but not together?

  • Specifically: https://stackoverflow.com/a/40750101/1904943

Improved plot layout

It is difficult to decrease congestion in these static networkx / matplotlib plots; one workaround is to increase the figure size, per this StackOverflow Q/A: High Resolution Image of a Graph using NetworkX and Matplotlib :

plt.figure(figsize=(20,14)) # <matplotlib.figure.Figure object at 0x7f1b65ea5e80>  nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \     node_size=1200, node_color='lightblue', linewidths=0.25, \     font_size=10, font_weight='bold', with_labels=True, dpi=1000)  plt.show()    ## plot2.png attached 

To reset the output figure size to the system default:

plt.figure() # <matplotlib.figure.Figure object at 0x7f1b454f1588> 

Bonus: shortest path

nx.dijkstra_path(G, 'CDKN1A', 'MLH3') # ['CDKN1A', 'CDK2', 'CHEK2', 'BRCA1', 'PTEN', 'MLH3']  

plot1.png plot1.png

plot2.png plot2.png


Although I did not do this here, if you want to add node borders and thicken the node border lines (node edge thickness: linewidths), do the following.

nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \     node_size=1200, node_color='lightblue', linewidths=2.0, \     font_size=10, font_weight='bold', with_labels=True) # Get current axis: ax = plt.gca() ax.collections[0].set_edgecolor('r') # r : red (can also use #FF0000) | b : black (can also use #000000) | ... plt.show() 
like image 45
Victoria Stuart Avatar answered Oct 01 '22 07:10

Victoria Stuart