使用toyplot绘制社区图时节点颜色映射异常问题排查
问题:Toyplot社区图颜色映射异常问题
我用Toyplot绘制带有源节点、目标节点的社区图,节点分属社区0和社区1,希望社区0节点显示为绿色、社区1节点显示为橙色,但颜色映射始终不正确。当把节点重命名为0-9(使用source2和target2字段)时,生成的图颜色显示正常,请问我忽略了什么问题?
import numpy as np import pandas as pd import toyplot nodes = ['1001', '1002', '1006', '100e', '010c', '0521', '0513', '0710', '0711', '1005'] mapped_nodes = ['0','1','2','3','4','5','6','7','8','9'] event_map = dict(zip(nodes,mapped_nodes)) edges = pd.DataFrame() edges['source'] = ['010c','0513','0513','0513','0513','0513','0521','0521','0521','0521','0710','0710','0710','1001','1002','1006'] edges['target'] = ['0521','0521','0710','0711','1001','1005','0710','1001','1002','1006','1006','0711','1005','1006','1006','100e'] edges['source2'] = edges['source'].map(event_map) edges['target2'] = edges['target'].map(event_map) print('display edges') display(edges) # 启用这行时节点颜色显示正常 # edges = np.array(edges[['source2','target2']].values.tolist()) # 启用这行时节点颜色显示异常,1005、0711、0513、0710本应显示社区1的颜色 edges = np.array(edges[['source','target']].values.tolist()) print('print edges') print(edges) assigned = pd.DataFrame() assigned['target'] = ['1001','1002','1006','100e','010c','0521','0513','0710','0711','1005'] assigned['target2'] = assigned['target'].map(event_map) assigned['community'] = [0,0,0,0,0,0,1,1,1,1] print('display assigned') display(assigned) assigned = np.array(assigned[['target','target2','community']].values.tolist()) print('print assigned') print(assigned) colormap = toyplot.color.brewer.map("Set2") display(colormap) ecolor = "lightgrey" vlstyle = {"fill":"white"} vcolor = assigned[:,2].astype(int) toyplot.graph(edges, ecolor=ecolor, vsize=20, vlstyle=vlstyle, vcolor=(vcolor, colormap))
问题根源
Toyplot的toyplot.graph()函数处理字符串类型的节点ID时,会自动按字符串的字典序为节点分配索引;而你传入的vcolor是按照自定义的assigned数组顺序排列的,两者的节点顺序不匹配,导致颜色对应错位。
当使用数字字符串(0-9)作为节点ID时,Toyplot的字典序排序刚好和你assigned里的target2顺序一致,所以颜色匹配正确;但使用原始字符串节点ID时,排序顺序和你定义的节点社区顺序完全不同,自然出现颜色映射错误。
解决方法
只需让vcolor的顺序和Toyplot内部生成的节点顺序完全一致,以下是两种可行方案:
方案1:手动指定节点顺序
调用toyplot.graph()时,通过nodes参数明确指定节点顺序,和assigned里的target顺序保持一致:
# 提取自定义的节点顺序 node_order = assigned[:,0].tolist() # 绘制时传入nodes参数锁定顺序 toyplot.graph(edges, nodes=node_order, ecolor=ecolor, vsize=20, vlstyle=vlstyle, vcolor=(vcolor, colormap))
方案2:按Toyplot节点顺序重排颜色数组
先生成图对象获取内部节点顺序,再重新排列颜色数组:
# 先创建图对象,获取Toyplot自动排序后的节点列表 graph = toyplot.graph(edges, ecolor=ecolor, vsize=20, vlstyle=vlstyle) toyplot_nodes = graph.nodes.keys() # 创建节点-社区映射字典 community_map = dict(zip(assigned[:,0], assigned[:,2].astype(int))) # 按Toyplot节点顺序生成对应颜色 sorted_vcolor = [community_map[node] for node in toyplot_nodes] # 更新节点颜色 graph.nodes.color = (sorted_vcolor, colormap)
效果验证
两种方案都能让原始字符串节点ID的颜色匹配正确,社区0显示绿色、社区1显示橙色,完全符合预期。
内容的提问来源于stack exchange,提问作者someds
相关产品推荐
相关产品推荐

