根据节点值为networkx中的节点绘制不同的颜色
Posted
技术标签:
【中文标题】根据节点值为networkx中的节点绘制不同的颜色【英文标题】:Draw different color for nodes in networkx based on their node value 【发布时间】:2012-11-11 03:23:59 【问题描述】:我有一个大的节点图和有向边。此外,我还有一个分配给每个节点的附加值列表。
我现在想根据节点值更改每个节点的颜色。例如,绘制具有非常高值红色的节点和具有低值蓝色的节点(类似于热图)。这是否很容易实现?如果没有 networkx,我也对 Python 中的其他库开放。
【问题讨论】:
【参考方案1】:对于一般情况,我们有一个值列表来指示节点的某些属性,并且我们希望为给定节点分配一种颜色,以给出该属性的 scale 感觉(例如从红到蓝),这是一种方法:
import matplotlib as mpl
from matplotlib import pyplot as plt
from pylab import rcParams
import networkx as nx
G = nx.Graph()
G.add_edges_from([('A', 'D'), ('Z', 'D'), ('F', 'J'), ('A', 'E'), ('E', 'J'),('Z', 'K'), ('B', 'A'), ('B', 'D'), ('A', 'J'), ('Z', 'F'),('Z', 'D'), ('A', 'B'), ('J', 'D'), ('J', 'E'), ('Z', 'J'),('K', 'J'), ('B', 'F'), ('B', 'J'), ('A', 'Z'), ('Z', 'E'),('C', 'Z'), ('C', 'A')])
假设我们有以下字典将每个节点映射到给定值:
color_lookup = k:v for v, k in enumerate(sorted(set(G.nodes())))
# 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'J': 6, 'K': 7, 'Z': 8
我们可以做的是使用mpl.colors.Normalize
将color_lookup
中的值标准化为基于节点所取的最小值和最大值的[0,1]
范围,然后matplotlib.cm.ScalarMappable
将标准化值映射到颜色图中的颜色,这里我将使用mpl.cm.coolwarm
:
low, *_, high = sorted(color_lookup.values())
norm = mpl.colors.Normalize(vmin=low, vmax=high, clip=True)
mapper = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.coolwarm)
rcParams['figure.figsize'] = 12, 7
nx.draw(G,
nodelist=color_lookup,
node_size=1000,
node_color=[mapper.to_rgba(i)
for i in color_lookup.values()],
with_labels=True)
plt.show()
对于另一个颜色图,我们只需要更改mpl.cm.ScalarMappable
中的cmap
参数:
mapper = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.summer)
nx.draw(G,
nodelist=color_lookup,
node_size=1000,
node_color=[mapper.to_rgba(i)
for i in color_lookup.values()],
with_labels=True)
plt.show()
我们会得到什么:
同样,我们可以根据节点的degree
来设置节点的颜色,方法是定义一个字典,将所有节点映射到对应的度,并采取与上述相同的步骤:
d = dict(G.degree)
# 'A': 6, 'D': 4, 'Z': 7, 'F': 3, 'J': 7, 'E': 3, 'K': 2, 'B': 4, 'C': 2
low, *_, high = sorted(d.values())
norm = mpl.colors.Normalize(vmin=low, vmax=high, clip=True)
mapper = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.coolwarm)
nx.draw(G,
nodelist=d,
node_size=1000,
node_color=[mapper.to_rgba(i)
for i in d.values()],
with_labels=True,
font_color='white')
plt.show()
【讨论】:
不错:低,*_,高 = 排序(d.values())【参考方案2】:import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edges_from(
[('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
('B', 'H'), ('B', 'G'), ('B', 'F'), ('C', 'G')])
val_map = 'A': 1.0,
'D': 0.5714285714285714,
'H': 0.0
values = [val_map.get(node, 0.25) for node in G.nodes()]
nx.draw(G, cmap=plt.get_cmap('viridis'), node_color=values, with_labels=True, font_color='white')
plt.show()
产量
values
中的数字与G.nodes()
中的节点相关联。
也就是说values
中的第一个数字与G.nodes()
中的第一个节点相关联,第二个也是如此,以此类推。
【讨论】:
以上是关于根据节点值为networkx中的节点绘制不同的颜色的主要内容,如果未能解决你的问题,请参考以下文章