使用Python可视化图结构:从GraphML文件生成节点关系图(lightrag 生成)

发布于:2025-03-25 ⋅ 阅读:(22) ⋅ 点赞:(0)

引言

在数据可视化领域,图结构(Graph)常用于展示实体间的复杂关系。例如,文学分析中的角色关系、社交网络中的用户互动等。本文将通过一个实际案例,演示如何使用 NetworkXMatplotlibGraphML 文件生成节点关系图,并解决常见问题(如节点标签不显示)。


实现步骤

1. 环境配置

确保已安装以下库:

pip install networkx matplotlib

2. 代码实现

import networkx as nx
import matplotlib.pyplot as plt

# 配置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取文件并转换为 MultiGraph
G = nx.read_graphml("dickens/graph_chunk_entity_relation.graphml")
if not isinstance(G, nx.MultiGraph):
    G = nx.MultiGraph(G)

# 创建新的 Graph 对象 GN,并确保包含所有节点和边
GN = nx.Graph()
GN.add_nodes_from(G.nodes())  # 添加所有节点(包括孤立节点)
for u, v, k in G.edges(keys=True):
    GN.add_edge(u, v)  # 添加所有边

# 生成布局(基于 GN 的结构)
pos = nx.spring_layout(GN)

# 绘制节点和边
nx.draw(
    GN,
    pos,
    with_labels=False,  # 关闭默认标签
    node_color='skyblue',
    node_size=1500,
    font_size=10
)

# 显式添加标签(基于 GN 的节点)
labels = {node: node for node in GN.nodes()}  # 使用 GN 的节点
nx.draw_networkx_labels(GN, pos, labels=labels, font_size=12, font_weight='bold')

# 调整图表样式
plt.title("节点关系图")
plt.axis('off')
plt.show()

代码解析

1. 中文显示配置

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置黑体显示中文
plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题
  • 作用:确保中文标签正常显示,避免乱码。

2. 图结构处理

# 读取文件并转换为 MultiGraph
G = nx.read_graphml("dickens/graph_chunk_entity_relation.graphml")
if not isinstance(G, nx.MultiGraph):
    G = nx.MultiGraph(G)
  • 关键点MultiGraph 支持多条边(如多个关系类型),若原图非 MultiGraph,需强制转换。

3. 构建简化图 GN

GN = nx.Graph()
GN.add_nodes_from(G.nodes())  # 添加所有节点(包括孤立节点)
for u, v, k in G.edges(keys=True):
    GN.add_edge(u, v)  # 添加所有边
  • 目的:将 MultiGraph 转换为普通 Graph,合并多重边(如仅保留边的存在性,忽略类型)。
  • 注意GN.add_nodes_from(G.nodes()) 确保包含所有节点(包括无边的孤立节点)。

4. 布局与绘制

pos = nx.spring_layout(GN)  # 力导向布局
nx.draw(GN, pos, with_labels=False, ...)
nx.draw_networkx_labels(GN, pos, labels=labels, ...)
  • 布局spring_layout 通过模拟物理力生成节点位置。
  • 标签显示:显式调用 nx.draw_networkx_labels 确保所有节点标签可见。

常见问题解答

Q1:节点标签未显示?

  • 原因:未显式调用 nx.draw_networkx_labels
  • 解决
    labels = {node: node for node in GN.nodes()}
    nx.draw_networkx_labels(GN, pos, labels=labels)
    

Q2:中文显示乱码?

  • 原因:未配置 matplotlib 字体。
  • 解决:添加以下代码:
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    

Q3:节点重叠或布局混乱?

  • 解决
    1. 调整 node_size 减小节点大小。
    2. 尝试其他布局算法:
      pos = nx.spectral_layout(GN)  # 谱布局
      pos = nx.circular_layout(GN)  # 环形布局
      

Q4:如何高亮特定节点?

  • 方法:通过 node_color 参数指定颜色列表:
    node_colors = ['red' if node == '张三' else 'skyblue' for node in GN.nodes()]
    nx.draw(GN, pos, node_color=node_colors)
    

扩展功能建议

1. 添加边类型区分

若需展示边类型(如强关系、弱关系),可结合 edge_color

edge_colors = []
for u, v, k in G.edges(keys=True):
    if G[u][v][k].get("type") == "weak":
        edge_colors.append('gray')
    else:
        edge_colors.append('black')
nx.draw(GN, pos, edge_color=edge_colors)

2. 交互式可视化

使用 networkx_viewer 实现交互式探索:

pip install networkx_viewer
from nxviz import CircosPlot
import networkx as nx
import networkx_viewer
G.add_node(1)
G.add_node(2)
G.add_edge(1,2)
networkx_viewer.view(G)

总结

本文通过一个实际案例,演示了如何从 GraphML 文件生成节点关系图,并解决了中文显示、标签缺失等常见问题。掌握这些技巧后,你可以轻松将文学分析、社交网络等数据转化为直观的可视化图表。如果需要进一步定制样式或功能,可以参考 NetworkX 官方文档


希望这篇博客能帮助你快速上手图结构可视化!如果有任何问题或改进建议,欢迎在评论区留言。