4、网络可视化基础:Matplotlib绘图、NetworkX绘图基础、布局算法
好,咱们进入第四章。网络可视化,说白了就是让数据「开口说话」。你模型建得再漂亮,算法跑得再快,最后拿不出一张像样的图,别人根本看不懂你在干什么。我当年做金融风控网络时,第一版图出来跟一团乱麻似的,被业务老大当场怼了一句「这玩意儿能看?」——嗯,从那以后,我老老实实把可视化基本功练扎实了。
这一章,咱们就搞定三件事:Matplotlib打底、NetworkX画图、布局算法调颜值。别急,一个一个来。
4.1 Matplotlib:可视化的「地基」
Matplotlib 是 Python 可视化的老大哥。虽然现在各种花哨库很多,但底层渲染基本都靠它。我个人习惯,不管用啥高级库,最后调细节时还是得回到 Matplotlib 的 API 上。
4.1.1 基本绘图流程
先看一个最简单的例子:
import matplotlib.pyplot as plt
import numpy as np
# 创建画布
fig, ax = plt.subplots(figsize=(8, 6))
# 画点
x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]
ax.scatter(x, y, color='blue', s=100, label='节点')
# 加标签
ax.set_title('金融网络节点分布')
ax.set_xlabel('风险维度X')
ax.set_ylabel('风险维度Y')
ax.legend()
plt.show()
这里有个坑——plt.show() 在 Jupyter 里会自动显示,但在脚本里跑会阻塞。我建议你在调试时用 plt.savefig() 直接存图,省得每次都要关窗口。
fig, ax = plt.subplots() 时,figsize 参数用英寸单位。我一般设 (12, 8) 或 (16, 10),太小的图节点一多就挤成一团。
4.1.2 颜色与样式控制
金融网络里,节点颜色往往代表不同含义——比如红色代表高风险,绿色代表低风险。你可以用 cmap 映射:
import matplotlib.cm as cm
risk_scores = [0.1, 0.5, 0.8, 0.3, 0.9]
colors = cm.RdYlGn(risk_scores) # 红黄绿渐变色
ax.scatter(x, y, c=colors, s=200, edgecolors='black')
我曾经在项目里用错颜色映射,把高风险标成了蓝色,结果业务方看了半天说「这些蓝点是不是很安全?」——嗯,从那以后我每次都会检查颜色语义。
4.2 NetworkX:网络图的「瑞士军刀」
NetworkX 是 Python 里最常用的网络分析库。它内置了绘图功能,但说实话,默认样式挺丑的。不过别担心,咱们可以调。
4.2.1 创建并绘制简单网络
import networkx as nx
# 创建空图
G = nx.Graph()
# 添加节点和边
G.add_nodes_from([1, 2, 3, 4, 5])
G.add_edges_from([(1,2), (2,3), (3,4), (4,5), (5,1)])
# 绘制
pos = nx.spring_layout(G) # 布局算法,后面细讲
nx.draw(G, pos, with_labels=True, node_color='lightblue',
node_size=500, font_size=12, font_weight='bold')
plt.show()
你看,核心就三行:建图、算布局、画图。但实际项目中,图往往有几百上千个节点,这时候就得注意性能了。
draw() 函数在节点数超过 1000 时,渲染会非常慢。我建议超过 500 个节点时,改用 nx.draw_networkx() 系列函数,可以精细控制哪些元素画、哪些不画。
4.2.2 自定义节点和边
金融网络里,节点大小可以代表交易金额,边粗细代表交易频次:
# 假设节点权重
node_weights = {1: 100, 2: 50, 3: 200, 4: 80, 5: 150}
node_sizes = [w * 5 for w in node_weights.values()]
# 边权重
edge_weights = {(1,2): 10, (2,3): 5, (3,4): 20, (4,5): 8, (5,1): 15}
edge_widths = [w * 0.5 for w in edge_weights.values()]
nx.draw_networkx_nodes(G, pos, node_size=node_sizes, node_color='orange')
nx.draw_networkx_edges(G, pos, width=edge_widths, alpha=0.6)
nx.draw_networkx_labels(G, pos, font_size=10)
这样画出来的图,一眼就能看出哪些节点是「大玩家」,哪些交易是「高频通道」。我当年做反洗钱项目时,就是用这种可视化方式,帮分析师快速定位异常交易模式。
4.3 布局算法:让网络「长」得好看
布局算法决定了节点在画布上的位置。同一个网络,用不同布局,视觉效果天差地别。我个人经验是:没有最好的布局,只有最合适的布局。
4.3.1 常见布局算法对比
| 布局算法 | 特点 | 适用场景 | 速度 |
|---|---|---|---|
spring_layout |
力导向,节点互相排斥,边像弹簧 | 中小型网络,社区结构明显 | 中等 |
circular_layout |
节点均匀分布在圆环上 | 环形结构、对称网络 | 极快 |
kamada_kawai_layout |
基于距离的力导向,更稳定 | 需要保持距离比例的网络 | 较慢 |
spectral_layout |
基于拉普拉斯矩阵特征向量 | 大型网络,社区发现后可视化 | 快 |
random_layout |
随机分布 | 调试用,别当真 | 最快 |
为什么会这样?因为不同布局算法背后的数学假设不同。spring_layout 模拟物理力学,适合展示社区结构;spectral_layout 基于图论,适合展示全局结构。
4.3.2 实战:选对布局
假设你有一个金融交易网络,包含 50 个节点,明显分成 3 个社区:
# 生成示例网络
G = nx.barbell_graph(20, 10) # 两个社区加中间连接
# 试试不同布局
layouts = {
'spring': nx.spring_layout(G, seed=42),
'circular': nx.circular_layout(G),
'kamada_kawai': nx.kamada_kawai_layout(G),
'spectral': nx.spectral_layout(G)
}
fig, axes = plt.subplots(2, 2, figsize=(12, 12))
for ax, (name, pos) in zip(axes.flatten(), layouts.items()):
nx.draw(G, pos, ax=ax, node_color='lightgreen',
node_size=100, with_labels=False)
ax.set_title(name)
plt.tight_layout()
plt.show()
你想想看,spring_layout 会把两个「杠铃头」分开,中间连接部分拉长;circular_layout 则把所有节点均匀排布,看不出社区结构。所以,选布局前,先想清楚你想表达什么。
4.3.3 布局调参技巧
spring_layout 有几个关键参数:
k:节点间的理想距离,默认 1/sqrt(n)。调小会让图更紧凑。iterations:迭代次数,默认 50。调大能让布局更稳定,但更慢。seed:随机种子。固定后每次布局结果一致,方便复现。
我曾经在做一个 200 节点的网络时,默认布局一团乱麻。后来把 k 从 0.07 调到 0.15,iterations 加到 200,图瞬间清晰了。嗯,调参这种事,有时候就是试出来的。
4.4 本章小结
这一章咱们走通了网络可视化的三条路:
- Matplotlib 打地基,控制颜色、大小、样式
- NetworkX 画网络,节点、边、标签随心配
- 布局算法 定颜值,选对布局比啥都重要
记住一句话:可视化是给人看的,不是给机器看的。你画出来的图,要让一个不懂技术的业务人员也能一眼看出「哦,这几个节点关系很紧密」「这条边交易量很大」。能做到这一点,你的可视化就成功了。
下一章咱们会把这些可视化技巧,用到真实的金融网络数据上。到时候你会发现,原来那些枯燥的交易记录,画出来竟然这么有意思。