用《悲惨世界》数据打造交互式人物关系图:pyecharts实战指南
当维克多·雨果笔下那些鲜活的人物跃然纸上时,我们是否想过用数据可视化的方式重新解读这部文学经典?《悲惨世界》中错综复杂的人物关系网络,正是练习关系图可视化的绝佳素材。不同于冰冷的抽象数据,文学作品中的人物互动带着情感温度和叙事逻辑,让技术学习过程变得生动有趣。
1. 环境准备与数据获取
工欲善其事,必先利其器。在开始之前,我们需要准备好Python环境和必要的数据集。
首先通过pip安装pyecharts及其依赖项:
pip install pyecharts《悲惨世界》的人物关系数据集已成为网络图可视化的经典案例,我们直接使用公开的JSON格式数据。该数据集包含77个节点和254条边,每个节点代表小说中的一个角色,边则表示角色间的互动关系。
数据集结构示例:
{ "nodes": [ {"id": 0, "name": "冉阿让", "category": 0}, {"id": 1, "name": "芳汀", "category": 0} ], "links": [ {"source": 0, "target": 1, "value": 1} ], "categories": [ {"name": "主角"}, {"name": "配角"} ] }提示:在实际项目中,如果处理自己的数据集,建议先用pandas进行数据清洗和预处理,确保节点和边的格式统一。
2. 基础关系图构建
让我们从最简单的网络图开始,逐步添加交互功能和视觉优化。
2.1 加载并解析数据
首先读取JSON文件并提取关键元素:
import json from pyecharts import options as opts from pyecharts.charts import Graph with open('les-miserables.json', 'r') as f: data = json.load(f) # 构建节点列表 nodes = [ { 'name': node['name'], 'symbolSize': node.get('symbolSize', 10), 'category': node.get('category', -1) } for node in data['nodes'] ] # 构建边列表 links = [{'source': link['source'], 'target': link['target']} for link in data['links']] # 分类信息 categories = [{'name': cat['name']} for cat in data['categories']]2.2 绘制基础网络图
使用pyecharts的Graph类创建第一个可视化:
graph = Graph(init_opts=opts.InitOpts(width="1000px", height="800px")) graph.add( series_name="悲惨世界人物关系", nodes=nodes, links=links, categories=categories, layout="force", # 力导向布局 repulsion=50, # 节点间斥力 is_roam=True, # 允许缩放平移 label_opts=opts.LabelOpts(is_show=False) ) graph.set_global_opts(title_opts=opts.TitleOpts(title="《悲惨世界》基础关系图")) graph.render("basic_graph.html")此时生成的图表已经可以展示基本的人物关系,但存在几个明显问题:
- 节点大小相同,无法区分角色重要性
- 标签显示混乱
- 缺乏分类视觉区分
3. 高级可视化定制
3.1 节点与边的视觉优化
根据角色在小说中的出现频率调整节点大小,并为不同类别角色设置不同颜色:
# 优化后的节点处理 nodes_optimized = [] for node in data['nodes']: size = node.get('value', 5) * 2 # 根据互动频率计算大小 nodes_optimized.append({ 'name': node['name'], 'symbolSize': size, 'category': node['category'], 'itemStyle': { 'color': '#5470c6' if node['category'] == 0 else '#91cc75' } }) # 优化边样式 linestyle_opts = opts.LineStyleOpts( width=0.5, curve=0.3, opacity=0.7, color='source' # 边颜色跟随源节点 )3.2 环形布局与分类展示
尝试不同的布局方式能带来全新的视角。将布局改为环形(circular)可以清晰展现人物分类:
graph.add( series_name="悲惨世界人物关系", nodes=nodes_optimized, links=links, categories=categories, layout="circular", # 环形布局 is_rotate_label=True, label_opts=opts.LabelOpts(position="right"), linestyle_opts=linestyle_opts )关键参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
| layout | str | 布局方式,可选'force'(力导向)/'circular'(环形)/'none'(自定义) |
| is_rotate_label | bool | 是否旋转标签以适应环形布局 |
| repulsion | int | 节点间斥力大小,值越大节点间距越大 |
| edge_symbol | list | 边的箭头样式,如['none', 'arrow'] |
3.3 交互功能增强
添加悬停高亮和提示框,提升用户体验:
graph.set_series_opts( focus_node_adjacency=True, # 高亮相邻节点 tooltip_opts=opts.TooltipOpts( formatter="{b}: 关联度{c}" if '{c}' in '{b}' else "{b}" ) )4. 分析与解读可视化结果
完成的可视化作品不仅是一张漂亮的图表,更是理解小说人物关系的分析工具。
4.1 核心人物识别
通过节点大小和连接密度,我们可以快速识别小说的核心人物:
- 冉阿让:中心度最高的节点,与几乎所有主要角色都有联系
- 沙威:作为对立面角色,连接数仅次于主角
- 珂赛特和马吕斯:构成小说的另一条主线
4.2 社群结构分析
观察图中的聚类现象,可以发现小说中的几个主要群体:
- 主教与冉阿让:故事开端的核心关系
- 芳汀与德纳第夫妇:工厂与旅馆场景的人物群
- ABC之友社:学生革命团体
提示:在学术研究中,可以结合NetworkX等库计算具体的网络指标,如中心度、聚类系数等。
4.3 交互探索技巧
充分利用pyecharts的交互功能:
- 缩放和平移:鼠标滚轮缩放,拖拽平移
- 节点高亮:悬停查看人物详情和关联
- 图例筛选:点击图例隐藏/显示特定类别
- 右键复位:双击或右键恢复初始视图
5. 项目扩展与进阶应用
掌握了基础技巧后,我们可以尝试更多创意呈现方式。
5.1 时间轴动态展示
展现人物关系随时间的变化:
from pyecharts.charts import Timeline timeline = Timeline() for year in [1830, 1832, 1848]: # 小说关键时间点 # 根据时间过滤节点和边 filtered_nodes = [n for n in nodes if n['year'] <= year] filtered_links = [l for l in links if l['year'] <= year] graph = Graph().add( series_name=f"{year}年关系图", nodes=filtered_nodes, links=filtered_links, categories=categories ) timeline.add(graph, time_point=str(year))5.2 3D关系图
使用pyecharts的3D功能创建更立体的展示:
from pyecharts.charts import GraphGL graph_3d = GraphGL() graph_3d.add( series_name="3D关系图", nodes=nodes, links=links, categories=categories, layout="force3D", itemstyle_opts=opts.ItemStyleOpts(opacity=0.8) )5.3 导出与分享
将可视化成果应用于不同场景:
- 静态图片:使用selenium截图保存为PNG
- 网页嵌入:直接发布HTML文件
- PPT展示:复制为矢量图或插入网页对象
# 保存为图片示例 from pyecharts.render import make_snapshot from snapshot_selenium import snapshot make_snapshot(snapshot, graph.render(), "graph.png")在完成这个项目后,最让我惊喜的是发现可视化不仅没有削弱文学作品的魅力,反而通过新的维度展现了人物关系的复杂与精妙。特别是当把布局从力导向改为环形时,原本混乱的节点突然呈现出清晰的层级结构,这种发现的过程正是���据可视化的乐趣所在。