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.
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.
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.
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.
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
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
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 )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With