Networkx adjusting the Edge Length to show a Correlation Matrix

Viewed 43

On a Sample Data,

import pandas as pd
import numpy as np

ranstate = np.random.RandomState(0)
df = pd.DataFrame(ranstate.rand(10, 10))
df[0]=df[0]+df[1]
df[2]=df[0]+df[1]
df[7]=df[9]+df[8]

corr = df.corr()

import networkx as nx
links = corr.stack().reset_index()
links.columns = ['var1', 'var2', 'value']
 
# Keep only correlation over a threshold and remove self correlation (cor(A,A)=1)
links_filtered=links.loc[ (links['value'] > 0.7) & (links['var1'] != links['var2']) ]
 
# Build your graph
G=nx.from_pandas_edgelist(links_filtered, 'var1', 'var2')
 
# Plot the network:
nx.draw(G, with_labels=True, node_color='orange', node_size=400, edge_color='black', linewidths=1, font_size=15)

Sample Data

But with Real Data,

Real Data

How could I,

  • set the Minimum Edge Length so that nodes are readable,
  • Annotate The Edge with Correlation Coefficient,
  • Color Code the edge [ Light Share to Dark Shade based] based on Correlation Coefficient
1 Answers

Unfortunately, the default layout algorithm (nx.spring_layout) doesn't allow for minimum node distance specification. You could scale down the node sizes to make the edges more readable, but the real issue is the large amount of white space between the connected components of the graph, which forces the edges to be relatively scaled down in the drawing.

One solution that seems to work in this case is to use nx.kamada_kawai_layout instead. That is, for the "plot the network" section, do the following:

pos = nx.kamada_kawai_layout(G)
nx.draw(G, pos = pos, with_labels=True, node_color='orange', node_size=400, edge_color='black', linewidths=1, font_size=15)

Here's a version that labels and colors the edges according to intensity, once you have the links_filtered dataframe.

from matplotlib import cm

G=nx.from_pandas_edgelist(links_filtered, 'var1', 'var2', edge_attr = 'value')
pos = nx.kamada_kawai_layout(G)
values = [d['value'] for _,_,d in G.edges(data=True)]
edge_labels = {(a,b):round(d['value'],2) for a,b,d in G.edges(data=True)}

nx.draw(G, pos = pos, with_labels=True, node_color='orange', 
        node_size=400, edge_color = values, linewidths=1, 
        font_size=15, edge_cmap = cm.inferno, edge_vmax = 1.1)
nx.draw_networkx_edge_labels(G, pos=pos, edge_labels = edge_labels)

Example result (using your script with a lower edge threshold):

enter image description here

Related