0
votes

I'm learning how to visualise the relationship some clusters as a graph. Let say I have 10 clusters (0-9) and I have already compute a distance between them and store it on a dictionary, named cluster_dist, that looks like this:

defaultdict(int,
        {('9', '2'): 90.0541376578846,
         ('1', '5'): 35.89579773471981,
         ('0', '2'): 35.89411581688678,
         ('5', '9'): 38.71629863467774,
         ('3', '5'): 4.263508474490007,
         ('2', '8'): 23.178581625571567,
         ('2', '7'): 75.21291397588608,
         ('1', '2'): 5.785812660966547,
         ('4', '6'): 5.785812660966547,
         ('1', '4'): 5.785812660966547})

So keys of this dictionary are tuples that represent edges and the value of these is a type of distance that I calculate between each cluster. The higher the distance, I expect that they are further apart on a graph.

Is it possible to create a graph with this kind of input? I was trying something like this:

g.add_vertices(10)

for clusters, dist in cluster_dist.items():

    a,b = map(int, list(clusters))
    g.add_edge(a, b, weight = dist )

But here I am not sure how to plot this on a way that the weight is interpreted as distance. I am a complete noob with graphs and igraph, so I bet there is a better way to assign the distance attribute to each edge.

Is it possible to represent a network out of any set of predetermined distances between nodes? If so, what is the best way to do this with igraph in python? In the case is not mathematically possible to generate a network that represent a given set of distances, is there any method to represent an approximation?

Thanks for your time :)

2
A layout in igraph is just a list of vertex coordinates. If you can calculate them manually – you have the answer. Just a hint: the cycle in your graph 2-1-5-9 could not fit on a plane with those weights. - paiv

2 Answers

1
votes

Using networkx and the kamada_kawai_layout as layout respecting distances.

import networkx as nx
import matplotlib.pyplot as plt
cluster_dist = \
        {('9', '2'): 90.0541376578846,
         ('1', '5'): 35.89579773471981,
         ('0', '2'): 35.89411581688678,
         ('5', '9'): 38.71629863467774,
         ('3', '5'): 4.263508474490007,
         ('2', '8'): 23.178581625571567,
         ('2', '7'): 75.21291397588608,
         ('1', '2'): 5.785812660966547,
         ('4', '6'): 5.785812660966547,
         ('1', '4'): 5.785812660966547}

# convert to graph
G = nx.Graph()
for (node1,node2), weight in cluster_dist.items():
    G.add_edge(node1, node2, weight=weight)
# compute layout for plotting
pos = nx.kamada_kawai_layout(G, weight='weight')
nx.draw(G,pos)
# next code for labels is not really necessary, but I think it makes it clearer
labels = {k: round(v,2) for k,v in nx.get_edge_attributes(G,'weight').items()}
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels)
nx.draw_networkx_labels(G,pos)

plt.show()

Output:

enter image description here

0
votes

After understanding the concept of layout and digging more into the available functions for computing the layouts using weights, I find ways of representing the cluster distances.

import igraph as ig

g = ig.Graph()
g.add_vertices(10)

for clusters, dist in cluster_dist.items():
    
    a,b = map(int, list(clusters))
    g.add_edge(a, b, weight = 1/dist )
    
l = g.layout_fruchterman_reingold(weights=splicing_net.es['weight'])

ig.plot(g, layout=l,  vertex_label=range(10), edge_width=ig.rescale([1/x for x in splicing_net.es["weight"]], out_range=(0.03, 3)))

So far the Fruchterman-Reingold is generating good looking weighted networks. If anyone knows additional algorithms to calculated layouts that follow sets of cluster distances, please let me know :)