Networkx中DiGraph的边标注优化及边重叠避免问题求助
解决Networkx有向图可视化的三个问题
现有代码
import networkx as nx import matplotlib.pyplot as plt import pandas as pd # 假设data是已加载的DataFrame G = nx.from_pandas_edgelist(data, source='grad', target='to', edge_attr='count', create_using=nx.DiGraph()) weight = nx.get_edge_attributes(G, 'count') pos = nx.shell_layout(G, scale=1) nx.draw_networkx_nodes(G, pos, node_size=300, node_color='lightblue') nx.draw_networkx_labels(G, pos=pos, font_color='red') nx.draw_networkx_edges(G, pos=pos, edgelist=G.edges(), edge_color='black', connectionstyle='arc3, rad = 0.1') nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=weight) plt.show()
当前可视化存在的问题
- 边标注未完全显示,部分边没有标注
- 弧形边的标注位于弧线上,显示效果不佳
- 非双向边无需使用弧形,整体显示不够整洁
附数据(前50行,字典格式)
data_dict = { 'grad': {0: 'CUHK', 1: 'CUHK', 2: 'CUHK', 3: 'CUHK', 4: 'CUHK', 5: 'CUHK', 6: 'CUHK', 7: 'CUHK', 8: 'CityU', 9: 'CityU', 10: 'CityU', 11: 'CityU', 12: 'CityU', 13: 'CityU', 14: 'CityU', 15: 'HKBU', 16: 'HKU', 17: 'HKU', 18: 'HKU', 19: 'HKU', 20: 'HKU', 21: 'HKU', 22: 'HKU', 23: 'HKUST', 24: 'HKUST', 25: 'HKUST', 26: 'HKUST', 27: 'HKUST', 28: 'HKUST', 29: 'HKUST', 30: 'HKUST', 31: 'Low Frequency', 32: 'Low Frequency', 33: 'Low Frequency', 34: 'Low Frequency', 35: 'Low Frequency', 36: 'Low Frequency', 37: 'Low Frequency', 38: 'Low Frequency', 39: 'PolyU', 40: 'PolyU', 41: 'PolyU', 42: 'PolyU', 43: 'PolyU', 44: 'PolyU'}, 'to': {0: 'CUHK', 1: 'CityU', 2: 'EduHK', 3: 'HKBU', 4: 'HKU', 5: 'HKUST', 6: 'LingU', 7: 'PolyU', 8: 'CityU', 9: 'EduHK', 10: 'HKBU', 11: 'HKU', 12: 'HKUST', 13: 'LingU', 14: 'PolyU', 15: 'HKBU', 16: 'CUHK', 17: 'CityU', 18: 'EduHK', 19: 'HKBU', 20: 'HKU', 21: 'HKUST', 22: 'PolyU', 23: 'CUHK', 24: 'CityU', 25: 'EduHK', 26: 'HKBU', 27: 'HKU', 28: 'HKUST', 29: 'LingU', 30: 'PolyU', 31: 'CUHK', 32: 'CityU', 33: 'EduHK', 34: 'HKBU', 35: 'HKU', 36: 'HKUST', 37: 'LingU', 38: 'PolyU', 39: 'CityU', 40: 'EduHK', 41: 'HKBU', 42: 'HKU', 43: 'LingU', 44: 'PolyU'}, 'count': {0: 13, 1: 6, 2: 3, 3: 6, 4: 5, 5: 3, 6: 2, 7: 6, 8: 4, 9: 1, 10: 5, 11: 2, 12: 1, 13: 2, 14: 7, 15: 2, 16: 2, 17: 4, 18: 3, 19: 1, 20: 17, 21: 3, 22: 9, 23: 4, 24: 2, 25: 2, 26: 4, 27: 2, 28: 4, 29: 4, 30: 6, 31: 76, 32: 73, 33: 1, 34: 16, 35: 57, 36: 46, 37: 3, 38: 69, 39: 1, 40: 2, 41: 3, 42: 1, 43: 1, 44: 23} } # 转换为DataFrame data = pd.DataFrame(data_dict)
针对性解决方案
1. 修复边标注缺失问题
边标注缺失多因标签重叠、字体过大或被节点遮挡,调整以下参数即可解决:
- 缩小字体:
font_size=8 - 偏移标签位置:
label_pos=0.3(让标签靠近起点,避开节点遮挡) - 添加背景框:
bbox=dict(facecolor='white', edgecolor='none', alpha=0.7),避免标签被边或其他元素覆盖
2. 优化弧形边的标注显示
弧形边的标签不要放在弧线上,改为水平显示并偏移位置:
- 关闭标签旋转:
rotate=False - 调整标签位置到弧线外侧:
label_pos=0.2或0.8
3. 区分双向边与单向边的显示
先筛选出双向边(同时存在(u,v)和(v,u)的边),单向边用直线绘制,双向边用正反弧形区分:
# 筛选双向/单向边 bidirectional_edges = set() unidirectional_edges = set() seen = set() for u, v in G.edges(): if (v, u) in G.edges() and (u, v) not in seen and (v, u) not in seen: bidirectional_edges.add((u, v)) bidirectional_edges.add((v, u)) seen.add((u, v)) seen.add((v, u)) elif (u, v) not in seen: unidirectional_edges.add((u, v)) seen.add((u, v))
修改后的完整代码
import networkx as nx import matplotlib.pyplot as plt import pandas as pd # 加载数据 data_dict = { 'grad': {0: 'CUHK', 1: 'CUHK', 2: 'CUHK', 3: 'CUHK', 4: 'CUHK', 5: 'CUHK', 6: 'CUHK', 7: 'CUHK', 8: 'CityU', 9: 'CityU', 10: 'CityU', 11: 'CityU', 12: 'CityU', 13: 'CityU', 14: 'CityU', 15: 'HKBU', 16: 'HKU', 17: 'HKU', 18: 'HKU', 19: 'HKU', 20: 'HKU', 21: 'HKU', 22: 'HKU', 23: 'HKUST', 24: 'HKUST', 25: 'HKUST', 26: 'HKUST', 27: 'HKUST', 28: 'HKUST', 29: 'HKUST', 30: 'HKUST', 31: 'Low Frequency', 32: 'Low Frequency', 33: 'Low Frequency', 34: 'Low Frequency', 35: 'Low Frequency', 36: 'Low Frequency', 37: 'Low Frequency', 38: 'Low Frequency', 39: 'PolyU', 40: 'PolyU', 41: 'PolyU', 42: 'PolyU', 43: 'PolyU', 44: 'PolyU'}, 'to': {0: 'CUHK', 1: 'CityU', 2: 'EduHK', 3: 'HKBU', 4: 'HKU', 5: 'HKUST', 6: 'LingU', 7: 'PolyU', 8: 'CityU', 9: 'EduHK', 10: 'HKBU', 11: 'HKU', 12: 'HKUST', 13: 'LingU', 14: 'PolyU', 15: 'HKBU', 16: 'CUHK', 17: 'CityU', 18: 'EduHK', 19: 'HKBU', 20: 'HKU', 21: 'HKUST', 22: 'PolyU', 23: 'CUHK', 24: 'CityU', 25: 'EduHK', 26: 'HKBU', 27: 'HKU', 28: 'HKUST', 29: 'LingU', 30: 'PolyU', 31: 'CUHK', 32: 'CityU', 33: 'EduHK', 34: 'HKBU', 35: 'HKU', 36: 'HKUST', 37: 'LingU', 38: 'PolyU', 39: 'CityU', 40: 'EduHK', 41: 'HKBU', 42: 'HKU', 43: 'LingU', 44: 'PolyU'}, 'count': {0: 13, 1: 6, 2: 3, 3: 6, 4: 5, 5: 3, 6: 2, 7: 6, 8: 4, 9: 1, 10: 5, 11: 2, 12: 1, 13: 2, 14: 7, 15: 2, 16: 2, 17: 4, 18: 3, 19: 1, 20: 17, 21: 3, 22: 9, 23: 4, 24: 2, 25: 2, 26: 4, 27: 2, 28: 4, 29: 4, 30: 6, 31: 76, 32: 73, 33: 1, 34: 16, 35: 57, 36: 46, 37: 3, 38: 69, 39: 1, 40: 2, 41: 3, 42: 1, 43: 1, 44: 23} } data = pd.DataFrame(data_dict) # 创建图 G = nx.from_pandas_edgelist(data, source='grad', target='to', edge_attr='count', create_using=nx.DiGraph()) weight = nx.get_edge_attributes(G, 'count') pos = nx.shell_layout(G, scale=1) # 筛选双向/单向边 bidirectional_edges = set() unidirectional_edges = set() seen = set() for u, v in G.edges(): if (v, u) in G.edges() and (u, v) not in seen and (v, u) not in seen: bidirectional_edges.add((u, v)) bidirectional_edges.add((v, u)) seen.add((u, v)) seen.add((v, u)) elif (u, v) not in seen: unidirectional_edges.add((u, v)) seen.add((u, v)) # 绘制节点和标签 nx.draw_networkx_nodes(G, pos, node_size=300, node_color='lightblue') nx.draw_networkx_labels(G, pos=pos, font_color='red', font_size=9) # 绘制单向边(直线) nx.draw_networkx_edges(G, pos=pos, edgelist=unidirectional_edges, edge_color='black', arrowstyle='->') # 绘制双向边(不同方向弧形) seen_edges = set(bidirectional_edges) for u, v in bidirectional_edges: if (u, v) not in seen_edges: continue # 正向边用右弧形,反向边用左弧形 nx.draw_networkx_edges(G, pos=pos, edgelist=[(u, v)], edge_color='black', arrowstyle='->', connectionstyle=f'arc3, rad={0.1 if u < v else -0.1}') seen_edges.remove((u, v)) seen_edges.remove((v, u)) # 绘制边标签,优化显示 nx.draw_networkx_edge_labels(G, pos=pos, edge_labels=weight, font_size=8, label_pos=0.3, rotate=False, bbox=dict(facecolor='white', edgecolor='none', alpha=0.7)) plt.axis('off') plt.show()
内容的提问来源于stack exchange,提问作者kenny
相关产品推荐
相关产品推荐

