Anks
Anks

Reputation: 45

How to have different edge weights but same edge length in network diagram?

I am working with networkx in Python. I am facing an issue where I want to give different weightage to the different edges with same edge length for all.

Although with this code, with different weightage to edges, the length is also changing, which is undesirable.

I need some help with it.

Thanks in advance.

import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib as mpl

df = pd.DataFrame({'from': ['1', '2', '3', '4', '4', '4'], 'to': ['2', '3', '4', '5', '6', '7'], 'value': ['0.5', '0', '0', '0', '0', '0']})
df['value'] = pd.Categorical(df['value'])
df['value'].cat.codes


G = nx.from_pandas_edgelist(df, 'from', 'to', create_using=nx.Graph())

cmap = plt.cm.cool
vmax = float(max(df['value']))
vmin = float(min(df['value']))
norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)

G = nx.Graph()
G.add_edge(1, 2,  weight=5)
G.add_edge(2, 3,  weight=0.5)
G.add_edge(3, 4,  weight=0.5)
G.add_edge(4, 5,  weight=0.5)
G.add_edge(4, 6,  weight=0.5)
G.add_edge(4, 7,  weight=0.5)
edges = G.edges()
weights = [G[u][v]['weight'] for u,v in edges]

nc = nx.draw_networkx(G, with_labels=True, node_color='yellow', node_size=700, edge_color=df['value'].cat.codes, width=weights, edge_cmap=cmap, font_size=10, font_color='black', font_weight='bold')

sm = plt.cm.ScalarMappable(cmap=cmap, norm=mpl.colors.Normalize(vmin = vmin, vmax = vmax))
sm._A = []
plt.colorbar(sm)
plt.axis('off')

plt.show()

resulting plot

Upvotes: 2

Views: 1179

Answers (1)

JohanC
JohanC

Reputation: 80329

Default, a spring layout is used to layout the nodes. This often is the most pleasing. Also default, the spring layout uses the 'weight' attribute of the edges for their length. The heavier, the closer together. However, you can add your own attributes and tell spring_layout to use those. I named it 'draw_weight', but any name will do. You can also put it to None, which weights every edge equally (pos=nx.spring_layout(G, weight=None)).

You can also experiment with other layout algorithms as mentioned in the documentation to replace the default spring_layout.

import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib as mpl

df = pd.DataFrame({'from': ['1', '2', '3', '4', '4', '4'], 'to': ['2', '3', '4', '5', '6', '7'], 'value': ['0.5', '0', '0', '0', '0', '0']})
df['value'] = pd.Categorical(df['value'])
df['value'].cat.codes


G = nx.from_pandas_edgelist(df, 'from', 'to', create_using=nx.Graph())

cmap = plt.cm.cool
vmax = float(max(df['value']))
vmin = float(min(df['value']))
norm = mpl.colors.Normalize(vmin=vmin, vmax=vmax)

G = nx.Graph()
G.add_edge(1, 2,  weight=5,    draw_weight=1)
G.add_edge(2, 3,  weight=0.5,  draw_weight=1)
G.add_edge(3, 4,  weight=0.5,  draw_weight=1)
G.add_edge(4, 5,  weight=0.5,  draw_weight=1)
G.add_edge(4, 6,  weight=0.5,  draw_weight=1)
G.add_edge(4, 7,  weight=0.5,  draw_weight=1)
edges = G.edges()
weights = [G[u][v]['weight'] for u,v in edges]

nc = nx.draw_networkx(G, pos=nx.spring_layout(G, weight='draw_weight'),  with_labels=True, node_color='yellow', node_size=700, edge_color=df['value'].cat.codes, width=weights, edge_cmap=cmap, font_size=10, font_color='black', font_weight='bold')

sm = plt.cm.ScalarMappable(cmap=cmap, norm=mpl.colors.Normalize(vmin = vmin, vmax = vmax))
sm._A = []
plt.colorbar(sm)
plt.axis('off')

plt.show()

The resulting graph layout

Note that the edge lengths are never exactly equal, because the spring_layout tries to combine two strategies: to have nodes nicely separated and edge lengths close to the desired ones. For this example, the shell_layout would also look nice, but probably the idea is to have more complicated graphs. Some experimentation will be required.

Upvotes: 1

Related Questions