Python新手求助:如何在NetworkX中让边颜色匹配对应节点颜色?
让Louvain聚类图的边颜色匹配节点社区颜色
嘿,我看你在处理Louvain聚类后的网络图时,卡在了边颜色匹配节点社区色这一步——现在只能设单一颜色,没法和节点的社区对应上。其实问题出在你当前用节点位置计算颜色的逻辑,完全和社区不沾边,咱们换个思路就能解决!
核心思路
首先得把每个社区对应的颜色存下来(而不是画节点时用了就丢),然后对每条边,根据它连接的两个节点的社区来分配颜色:如果两个节点同属一个社区,就用这个社区的颜色;如果跨社区,可以选其中一端的颜色,或者做个颜色渐变,看你需求。
修改后的完整代码
import matplotlib.pyplot as plt import matplotlib.cm as cm import networkx as nx import community # 记得先装这个库:pip install python-louvain # 假设你的图G已经定义好了 # G = ... partition_louvain = community.best_partition(G) size = float(len(set(partition_louvain.values()))) pos = nx.spring_layout(G) communities_louvain = [] cmap = cm.get_cmap("BlueRedGreen") # 或者你自己定义的mymap # 先把每个社区对应的颜色存进字典,方便后面边调用 community_colors = {} count = 0. for com in set(partition_louvain.values()): current_color = cmap(count / size) community_colors[com] = current_color count += 1. # 绘制节点 list_nodes = [node for node in partition_louvain if partition_louvain[node] == com] communities_louvain.append(list_nodes) nx.draw_networkx_nodes(G, pos, list_nodes, node_size=20, node_color=current_color) # 开始绘制边,匹配社区颜色 ax = plt.gca() for u, v, attrs in G.edges(data=True): # 获取两个节点的社区ID com_u = partition_louvain[u] com_v = partition_louvain[v] # 颜色策略:同社区用社区色,跨社区可以选其中一个(这里选u的社区色) if com_u == com_v: edge_color = community_colors[com_u] else: edge_color = community_colors[com_u] # 也可以换成community_colors[com_v] # 绘制箭头边 ax.annotate("", xy=pos[u], xycoords='data', xytext=pos[v], textcoords='data', arrowprops=dict( arrowstyle="->", color=edge_color, shrinkA=5, shrinkB=5, patchA=None, patchB=None, connectionstyle=f"arc3,rad={0.3 * attrs.get('weight', 0)}" # 更简洁的写法 ) ) plt.axis('off') # 关掉坐标轴,图更清爽 plt.show()
关键改动点
- 新增了
community_colors字典,把每个社区ID和对应的颜色绑定,这样边可以直接复用节点的社区色,不用重复计算。 - 遍历边时,通过节点ID拿到对应的社区,再从字典里取颜色,替代了你之前用节点坐标算颜色的逻辑(那个逻辑和社区完全无关)。
- 把边的弧度计算改成了
attrs.get('weight', 0),更安全——如果你的边没有weight属性,也不会报错。
可选优化:跨社区边用渐变色
如果你想让连接不同社区的边显示两个社区的过渡色,可以加个颜色混合的逻辑:
from matplotlib.colors import to_rgb # 在跨社区的分支里替换成这个: color_u = to_rgb(community_colors[com_u]) color_v = to_rgb(community_colors[com_v]) # 取两种颜色的平均值作为混合色 mixed_color = tuple((c1 + c2)/2 for c1, c2 in zip(color_u, color_v)) edge_color = mixed_color
这样跨社区的边颜色会是两个社区色的中间值,视觉上更连贯哦!
内容的提问来源于stack exchange,提问作者Skirlen
相关产品推荐
相关产品推荐

