用 Vue.js 与 D3.js 打造自定义社交网络可视化应用:Data Science for Beginners 第 13 课实战
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
本文基于 Data Science for Beginners 课程第 13 课「Making Meaningful Visualizations」的课后作业任务(Build your own custom vis)展开,完整讲解如何以仓库内置的 Dangerous Liaisons(《危险关系》)示例项目为底座,使用 Vue.js 与vue-d3-network库构建一个可交互的社交网络可视化 Web 应用。读完本文,你将掌握 D3 网络图的节点/边数据结构、核心createLinks()逻辑的补全原理、如何把自有社交数据(社交媒体使用记录、家庭成员关系等)改造成可视化数据,以及将成果打包部署为静态 Web 应用的完整流程。
作业任务解读:构建你自己的自定义可视化
本课作业(作业原文)的要求可以归纳为一句话:使用本课程项目中的代码样例创建一个社交网络,并模拟一份属于自己的社交互动数据。两种官方推荐的切入点:
- 把你自己的社交媒体使用情况映射成网络图(谁与谁互动、互动频次如何);
- 或者绘制一张家庭成员关系图(亲属之间的连接关系)。
最终目标是产出一个「有趣的 Web 应用」,展示一个独一无二的社交网络可视化。这与本课 README 的课程目标一脉相承——有意义的数据可视化要能帮助回答你真正关心的问题,而网络图正适合表达「谁与谁相连」这类关系型问题。
从小说信件数据到社交网络图谱:项目原理
课程项目选用了 1782 年法国作家 Choderlos de Laclos 的书信体小说《危险关系》(Les Liaisons Dangereuses)。这部小说由一系列人物之间往来的信件构成,天然就是一份「谁给谁写了信」的社交关系数据——每个写信人/收信人就是一个节点,每一封信就是一条边。
数据文件:letters.json
仓库在 starter/src/assets/letters.json 中提供了小说全部信件的结构化数据,每一条记录包含如下字段:
{ "letter_num": 1, "from": "Cécile de Volanges", "to": "Sophie Carnay", "date": "8/3/17**", "location": "Ursulines" }字段含义:
| 字段 | 说明 |
|---|---|
letter_num | 信件编号,用于排序与定位 |
from | 写信人(边的起点) |
to | 收信人(边的终点) |
date | 信件日期(小说虚构年代,以17**表示) |
location | 写信地点(部分记录缺省该字段) |
整份 JSON 共 1261 行,涵盖 15 位主要人物。课程 README 指出:这是一部「由一系列写给圈子内不同人物的信件展开、策划复仇或仅仅为了惹麻烦」的小说,可视化这些信件,就能直观地发现谁是叙事中的「关键枢纽人物」(kingpin)。
渲染库:vue-d3-network
应用没有从零手写 D3 布局,而是使用了专为 Vue.js + D3 设计的网络可视化组件库vue-d3-network(版本 0.1.28,见 starter/package.json)。它把 D3 的力导向布局封装为声明式组件:
<d3-network :net-nodes="nodes" :net-links="links" :options="options" />应用运行后,你可以用鼠标拖动节点在屏幕上移动、打乱布局,直观体验网络拓扑的交互性。
环境准备与项目启动
starter 目录是未完成的练习项目,solution目录则存放完成版参考答案。启动前需确认本机已安装NPM 与 Node.js ≥ 20.0.0(该约束同时声明在 package.json 的engines字段中)。
# 安装依赖 npm install # 开发模式:编译并热重载 npm run serve # 生产构建:编译并压缩 npm run build # 代码检查与修复 npm run lint依赖清单的核心部分(来自 starter/package.json):
| 依赖 | 版本 | 作用 |
|---|---|---|
vue | ^3.5.16 | 前端框架 |
vue-d3-network | 0.1.28 | 网络图可视化组件 |
core-js | ^3.6.5 | 兼容性 polyfill |
@vue/cli-service | ~5.0.8 | Vue CLI 构建服务 |
核心实现:补全 createLinks() 函数
练习的关键一步,是完成 starter/src/components/Nodes.vue 中的createLinks()方法——把letters.json里的from/to人名解析为可视化库能消费的链接对象({ sid, tid })。
完整实现代码
createLinks(characters) { //loop through letters let f = 0; let t = 0; for (var i = 0; i < letters.length; i++) { for (var j = 0; j < characters.length; j++) { if (characters[j] == letters[i].from) { f = j; } if (characters[j] == letters[i].to) { t = j; } } this.links.push({ sid: f, tid: t }); } }该实现与 solution/src/components/Nodes.vue 中的参考答案完全一致。
逐段拆解执行逻辑
- 外层循环遍历信件:
for (var i = 0; i < letters.length; i++)逐封处理letters.json中的记录; - 内层循环匹配人物下标:对每一封信,在
characters数组(15 位人物的名称列表)中找出写信人letters[i].from和收信人letters[i].to对应的数组下标,分别存入f和t; - 生成链接对象:
this.links.push({ sid: f, tid: t }),sid(source id)与tid(target id)正是vue-d3-network所需的节点索引对。
也就是说:边表不是手工维护的,而是从「信件记录 × 人物名单」两重循环中自动派生出来的。人物名单定义在组件的created()钩子中:
let characters = [ "Chevalier Danceny", "Marquise de Merteuil", "Cécile Volanges", "Présidente de Tourvel", "Azolan, chasseur", "Madame de Rosemonde", "Madame de Volanges", "Vicomte de Valmont", "Père Anselme", "...", "M. Bertrand", "Anonyme", "Sophie Carnay", "Maréchale de ***", "Le Comte de Gercourt" ];配套的节点构建逻辑
created()钩子中同时构建节点数组,注意其中两处与「有意义」直接相关的设计:
this.nodes.push({ id: j, name: characters[j], _size: this.getCount(characters[j]) + 20, _color: "#" + Math.floor(Math.random() * 16777215).toString(16), });- 节点大小承载语义:
_size由getCount(name)计算得出——统计该人物作为收信人(letters[i].to === name)的次数并加上 20 作为基础尺寸。收信越多,节点越大,恰好呼应课程「发现叙事关键枢纽人物」的目标; - 颜色随机生成:
_color使用随机十六进制颜色,方便在视觉上区分节点。
options计算属性则控制整个网络图的渲染参数:
options() { return { force: 3000, // 力导向布局的引力量级 size: { w: 600, h: 600 }, // 画布尺寸 offset: { x: 0, y: 0 }, // 画布偏移 nodeLabels: true, // 显示节点标签 linkLabels: true, // 显示连线标签 canvas: this.canvas, // 是否使用 canvas 渲染(默认 false,即 SVG) }; }把数据换成你自己的:两个实战方案
作业要求「mock up data of your own social interactions」,改造成自己的数据集只需三步:
- 替换数据文件:仿照 letters.json 的结构,新建一份自己的 JSON,字段至少保留
from与to(其余字段可自由扩展,如时间、平台、关系类型); - 更新人物名单:把
Nodes.vue中created()里的characters数组替换为你自己的实体名单(朋友、家人、平台账号等),确保与 JSON 中出现的名字一一对应; - 按需调整统计口径:如果想让节点大小反映别的含义(如发信数、互动总次数),可以仿照
getCount()编写新的统计方法。
方案一:社交媒体使用记录
把from/to定义为互动双方,例如:
[ { "interaction_id": 1, "from": "Alice", "to": "Bob", "channel": "wechat", "date": "2026-01-03" }, { "interaction_id": 2, "from": "Bob", "to": "Carol", "channel": "twitter", "date": "2026-01-05" } ]letters数组与getCount的命名可保留(代码内部一致性),可视化结果即为你社交圈的互动密度图。
方案二:家庭成员关系图
[ { "relation_id": 1, "from": "爷爷", "to": "爸爸", "relation": "父子" }, { "relation_id": 2, "from": "爸爸", "to": "我", "relation": "父子" } ]此时节点大小代表该成员的连接数,天然呈现家族核心人物。
让图表更有意义:配色、可读性与去欺骗性
本课作业虽聚焦「做出自己的可视化」,但课程的评判内核在于「有意义」。课程 README 给出了三条值得内化到自定义应用中的准则:
- 选择正确的图表类型:时间趋势用折线图,类别比较用柱状/饼图,关系展示用散点/网络图——社交网络场景下,节点-连线图(即本项目的网络图)正是「Show relationships」的正确选择;
- 避免欺骗性图表:颠倒坐标轴、翻转 Y 轴、用颜色误导、比较不可比对象都是常见的欺骗手法。课程特别提醒:即使意图良好,选错图表类型(例如用饼图展示过多类别)也可能产生误导;
- 谨慎使用颜色:颜色会承载额外的含义(如红色常表力量、蓝色表信任忠诚),且要考虑色盲用户的可用性。这也是为什么
Nodes.vue的样式表为.node、.link分别定义了清晰的填充色、悬停高亮(hover 时描边变为金色并加粗)以及选中态样式。
此外,课程强调「不可读的图表没有意义」:节点标签、连线标签(nodeLabels、linkLabels已默认开启)、适当的图例与提示都是提升可读性的基本手段。
部署为静态 Web 应用
作业评分标准特别鼓励将项目「作为静态 Web 应用部署」。Vue CLI 项目的构建产物是纯静态文件,任何静态托管平台均可承载:
npm run build构建完成后,将dist/目录下的全部文件上传至任意静态托管服务即可。这也是评分表(rubric)中「代码能正常运行」的验收前提之一。
评分标准与验收清单
作业原文给出了三档评分标准,可作为自测清单:
| 优秀(Exemplary) | 合格(Adequate) | 需改进(Needs Improvement) |
|---|---|---|
| 提交一个 GitHub 仓库,代码可正常运行(尝试部署为静态 Web 应用),且包含带注释的 README 解释项目 | 仓库不能正常运行,或文档不完善 | 仓库不能正常运行,且文档不完善 |
对照清单自查:
- 代码是否完整可运行(
npm install+npm run serve无报错,createLinks()已补全); - 是否已用
npm run build验证生产构建并通过静态部署上线; - README 是否对项目背景、数据来源、运行步骤和实现思路做了注释说明。
进阶挑战
完成基础任务后,可参考课程 README 的挑战环节拓展:到互联网上寻找欺骗性可视化案例,分析作者如何误导用户、是故意还是无意,并尝试纠正它们;或者参考课程中关于动画与 3D 展示的介绍,为网络图增加动画交互——例如让节点按照信件时间序列逐步出现,动态呈现社交关系的演变过程。课程还提到 Matplotlib 的mpl_toolkits.mplot3d可绘制 3D 图(见 images/3d.png),在数据支持时也可作为补充手段。
【免费下载链接】Data-Science-For-Beginners10 Weeks, 20 Lessons, Data Science for All!项目地址: https://gitcode.com/GitHub_Trending/da/Data-Science-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考