Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing a graph or a network from a distance matrix?

I'm trying to plot/sketch (matplotlib or other python library) a 2D network of a big distance matrix where distances would be the edges of the sketched network and the line and column its nodes.

DistMatrix = [       'a',   'b',     'c',    'd'], ['a',   0,      0.3,    0.4,    0.7], ['b',   0.3,    0,      0.9,    0.2], ['c',   0.4,    0.9,    0,      0.1], ['d',   0.7,    0.2,    0.1,    0] ] 

I'm searching to sketch/plot the 2d network from such (bigger: thousand of columns and lines) distance matrix: node 'a' is linked to node 'b' by an edge depth of 0.3, nodes 'c' and 'd' would be tied by an edge depth of 0.1. What are the tools/libraries I can used (distance matrix can be converted into numpy matrix) to get the sketch/graphical projection of such network? (pandas, matplotlib, igraph,...?) and some leads to do that quickly (I would not define my self Tkinter function to do that ;-) ) ? thanks for your incoming answers.

like image 271
sol Avatar asked Nov 22 '12 13:11

sol


People also ask

What is distance matrix of a graph?

In general, a distance matrix is a weighted adjacency matrix of some graph. In a network, a directed graph with weights assigned to the arcs, the distance between two nodes of the network can be defined as the minimum of the sums of the weights on the shortest paths joining the two nodes.

How does a distance matrix work?

A distance matrix is a table that shows the distance between pairs of objects. For example, in the table below we can see a distance of 16 between A and B, of 47 between A and C, and so on. By definition, an object's distance from itself, which is shown in the main diagonal of the table, is 0.

What is the difference between a distance matrix and an adjacency matrix?

The adjacency matrix represents the presence or absence of an edge connecting two vertices, while the distance matrix represents the shortest path between two vertices.


2 Answers

The graphviz program neato tries to respect edge lengths. doug shows a way to harness neato using networkx like this:

import networkx as nx import numpy as np import string  dt = [('len', float)] A = np.array([(0, 0.3, 0.4, 0.7),                (0.3, 0, 0.9, 0.2),                (0.4, 0.9, 0, 0.1),                (0.7, 0.2, 0.1, 0)                ])*10 A = A.view(dt)  G = nx.from_numpy_matrix(A) G = nx.relabel_nodes(G, dict(zip(range(len(G.nodes())),string.ascii_uppercase)))      G = nx.drawing.nx_agraph.to_agraph(G)  G.node_attr.update(color="red", style="filled") G.edge_attr.update(color="blue", width="2.0")  G.draw('/tmp/out.png', format='png', prog='neato') 

yields

enter image description here


If you want to generate a dot file, you can do so using

G.draw('/tmp/out.dot', format='dot', prog='neato') 

which yields

strict graph {     graph [bb="0,0,226.19,339.42"];     node [color=red,         label="\N",         style=filled     ];     edge [color=blue,         width=2.0     ];     B    [height=0.5,         pos="27,157.41",         width=0.75];     D    [height=0.5,         pos="69,303.6",         width=0.75];     B -- D   [len=2.0,         pos="32.15,175.34 40.211,203.4 55.721,257.38 63.808,285.53"];     A    [height=0.5,         pos="199.19,18",         width=0.75];     B -- A   [len=3.0,         pos="44.458,143.28 77.546,116.49 149.02,58.622 181.94,31.965"];     C    [height=0.5,         pos="140.12,321.42",         width=0.75];     B -- C   [len=9.0,         pos="38.469,174.04 60.15,205.48 106.92,273.28 128.62,304.75"];     D -- A   [len=7.0,         pos="76.948,286.17 100.19,235.18 167.86,86.729 191.18,35.571"];     D -- C   [len=1.0,         pos="94.274,309.94 100.82,311.58 107.88,313.34 114.45,314.99"];     A -- C   [len=4.0,         pos="195.67,36.072 185.17,90.039 154.1,249.6 143.62,303.45"]; } 

The png file could then be generated using the graphviz neato program:

neato -Tpng -o /tmp/out.png /tmp/out.dot  
like image 88
unutbu Avatar answered Oct 04 '22 13:10

unutbu


You can use the networkx package, that work perfectly with this kind of problems. Adjust your matrix to remove a simple numpy array like this:

DistMatrix =array([[0,      0.3,    0.4,    0.7], [0.3,    0,      0.9,    0.2], [0.4,    0.9,    0,      0.1], [0.7,    0.2,    0.1,    0] ]) 

then import networkx and use it

import networkx as nx G = G=nx.from_numpy_matrix(DistMatrix) nx.draw(G) 

if you want to draw a weighted version of the graph, you have to specify the color of each edge (at least, I couldn't find a more automated way to do it):

nx.draw(G,edge_color = [ i[2]['weight'] for i in G.edges(data=True) ], edge_cmap=cm.winter ) 
like image 23
EnricoGiampieri Avatar answered Oct 04 '22 14:10

EnricoGiampieri