【免费下载链接】networkx
Network Analysis in Python
导读
本文聚焦 NetworkX 的 drawing 模块(源码位于 networkx/drawing),系统讲解其内置的 Matplotlib 绘图 API、节点布局算法(layout),以及如何将图导出到 Graphviz(DOT)、iplotx、Hiveplotlib、LaTeX/TikZ 等专业可视化生态。读完本文,你将掌握 nx.draw 系列函数的核心参数、十余种布局算法的适用场景,以及把 NetworkX 图无缝桥接到外部渲染引擎的完整工作流,从而在"图分析"与"图可视化"之间做出正确的技术选型。
需要先说明的是:NetworkX 的定位是图分析而非图可视化(见 doc/reference/drawing.rst 开篇声明)。它提供的绘图功能是"够用就好"的基础能力,未来甚至可能被移除或改为独立附加包。因此本文一方面完整讲解内置绘图能力,另一方面也会给出"何时应该把图交给专业工具"的清晰判断标准。
一、定位与选型:NetworkX 绘图能做什么、不能做什么
1.1 官方定位:分析优先,可视化为辅
从 doc/reference/drawing.rst 可以明确读到官方立场:
NetworkX provides basic functionality for visualizing graphs, but its main goal is to enable graph analysis rather than perform graph visualization.
这意味着 networkx.drawing 提供的是基础可视化功能,而真正的目标是支撑图分析。官方甚至警告:在未来版本中,可视化功能可能从 NetworkX 移除,或仅作为附加包提供。
1.2 什么时候应该交给专业可视化工具
"好的图可视化很难"(Proper graph visualization is hard),官方明确推荐在需要高质量可视化时使用专门工具,包括:
- Cytoscape:生物网络分析利器,可直接读取 GraphML 格式
- Gephi:交互式图探索与可视化
- Graphviz:DOT 语言驱动的经典布局引擎
- Hiveplotlib:蜂巢图(hive plot)绘制
- iplotx:基于 Matplotlib 的扩展样式绘制
- PGF/TikZ:面向 LaTeX 排版的图绘制
数据导出桥接是使用这些工具的标准路径:先导出为对方可读的格式,再由外部工具渲染。例如 Cytoscape 能读取 GraphML,那么 networkx.write_graphml(G, path) 就是最合适的衔接调用(GraphML 读写实现在 networkx/readwrite/graphml.py)。
特别提示:文档中的 tip 明确指出,iplotx 与 hiveplotlib 可以直接接收 NetworkX 原生数据结构(图对象),无需导出为文件即可绘图。这意味着这两类工具与 NetworkX 的集成最为顺滑。
1.3 绘图模块全景
networkx/drawing 目录下共五个核心模块(见 networkx/drawing/init.py):
| 模块文件 | 职责 | 依赖 |
|---|---|---|
| nx_pylab.py | Matplotlib 绘图(draw 系列) | matplotlib |
| layout.py | 节点布局算法(返回 pos 字典) | numpy |
| nx_agraph.py | Graphviz 桥接(pygraphviz/AGraph) | pygraphviz、graphviz |
| nx_pydot.py | Graphviz 桥接(pydot) | pydot、graphviz |
| nx_latex.py | 导出 LaTeX/TikZ 代码 | 无(纯文本生成) |
注意:这些模块的依赖均为可选依赖,绘图前需确保对应依赖已安装(参考 requirements/extra.txt 中的可选依赖声明)。
二、Matplotlib 绘图:draw 系列函数全解
2.1 公共 API 一览
nx_pylab.py 的 __all__(见 nx_pylab.py)声明了以下公共函数:
display:在画布(canvas)上显示图apply_matplotlib_colors:从 matplotlib colormap 计算颜色并写回图属性draw:快速绘图入口draw_networkx:全功能绘图入口draw_networkx_nodes/draw_networkx_edges/draw_networkx_labels/draw_networkx_edge_labels:分层绘制节点、边、标签draw_bipartite/draw_circular/draw_kamada_kawai/draw_planar/draw_random/draw_spectral/draw_spring/draw_shell/draw_forceatlas2:绑定固定布局的便捷绘图
2.2 nx.draw:最简入口
draw(G, pos=None, ax=None, **kwds)(定义见 nx_pylab.py)是官方示例中最常用的快速入口:
import networkx as nx
G = nx.dodecahedral_graph()
nx.draw(G) # 不传 pos,自动使用 spring layout
nx.draw(G, pos=nx.spring_layout(G)) # 显式指定布局
其内部行为从源码可以拆解出几个关键点:
- 画布处理:未传
ax时使用plt.gcf()获取当前 figure,并把facecolor设为白色;若无坐标轴则通过cf.add_axes((0, 0, 1, 1))创建全图区坐标轴。 - 默认不带标签:
draw是"简洁模式",默认不画节点/边标签、不显示坐标轴刻度(绘制后调用ax.set_axis_off())。 - 标签开关联动:
with_labels默认值由"labels" in kwds推断——即只要你传入了labels字典,就会自动开启标签绘制(见源码 L1175-L1176)。 - 命名冲突警告:
draw与pylab.draw/pyplot.draw同名,from networkx import *时可能覆盖后者。源码 Notes 中建议区分使用:
import matplotlib.pyplot as plt
nx.draw(G) # networkx 的 draw()
plt.draw() # pyplot 的 draw()
2.3 nx.draw_networkx:全功能入口与核心参数
draw_networkx(G, pos=None, arrows=None, with_labels=True, **kwds)(nx_pylab.py)是参数最完整的绘制函数。它通过 inspect.signature 动态校验关键字参数(源码 L1335-L1357):任何不属于 draw_networkx_nodes、draw_networkx_edges、draw_networkx_labels 的参数都会抛出 ValueError,从机制上避免了"拼错参数名静默忽略"的问题。
核心参数表(均来自源码 docstring):
| 参数 | 默认值 | 说明 |
|---|---|---|
pos | None(自动 spring) | 节点位置字典,键为节点、值为二维坐标 |
arrows | None | None:有向图用 FancyArrowPatch 画箭头、无向图用 LineCollection(更快);True 强制画箭头;False 全部用 LineCollection |
arrowstyle | '-|>'(有向图) | 箭头样式,无向图默认 '-',详见 matplotlib.patches.ArrowStyle |
arrowsize | 10 | 箭头长度与宽度;可传列表分别设置 |
with_labels | True | 是否绘制节点标签 |
nodelist / edgelist | list(G) / list(G.edges()) | 只绘制指定节点/边 |
node_size | 300 | 节点大小,数组需与 nodelist 等长 |
node_color | '#1f78b4' | 节点颜色;数值序列会被 cmap/vmin/vmax 映射 |
node_shape | 'o' | 节点形状,取自 'so^>v<dph8' |
alpha | None | 节点与边透明度 |
cmap / vmin / vmax | None | 节点颜色映射的 colormap 与数值范围 |
width | 1.0 | 边线宽(可传数组逐边设置) |
edge_color | 'k' | 边颜色,可用 edge_cmap/edge_vmin/edge_vmax 映射 |
style | solid | 边线型:'-'、'--'、'-.'、':' |
font_size / font_color / font_weight / font_family | 12(边 10)/ 'k' / normal / sans-serif | 标签文本样式 |
label | None | 图例标签 |
hide_ticks | True | 隐藏坐标轴刻度与刻度标签;设为 False 恢复 pyplot 默认 |
ax | None | 指定 Matplotlib 坐标轴对象 |
组合使用示例(节点按度着色、边按权重着色):
import matplotlib.pyplot as plt
G = nx.dodecahedral_graph()
degrees = dict(G.degree())
nx.draw_networkx(
G,
pos=nx.spring_layout(G, seed=42),
nodelist=list(degrees),
node_size=[v * 100 for v in degrees.values()],
node_color=list(degrees.values()),
cmap=plt.cm.viridis,
with_labels=False,
)
plt.axis("off")
2.4 分层绘制:节点、边、标签的细粒度控制
draw_networkx 内部实质是依次调用三个子函数(源码 L1366-L1369),你完全可以分步调用以获得最大控制力:
draw_networkx_nodes(G, pos, nodelist, node_size, node_color, node_shape, alpha, cmap, vmin, vmax, ax, linewidths, edgecolors, label, margins, hide_ticks)(nx_pylab.py):仅绘制节点,底层对应matplotlib.pyplot.scatter的 marker 体系;linewidths控制节点描边宽度,edgecolors控制描边颜色(默认与节点同色)。draw_networkx_edges(G, pos, edgelist, ...)(nx_pylab.py):仅绘制边,支持arrows、arrowstyle、width、edge_color、style、connectionstyle(弯曲边)等。draw_networkx_labels(G, pos, labels, ...)(nx_pylab.py)与draw_networkx_edge_labels(G, pos, edge_labels, ...)(nx_pylab.py):分别绘制节点与边的文本标签,labels/edge_labels为{对象: 文本}字典。
分步绘制的典型收益:可以只画一次边、多次叠加不同子集的节点,实现"高亮社团"这类效果。
2.5 布局绑定便捷函数
nx_pylab.py 提供了一组与布局一一对应的便捷函数(等价于 draw(G, pos=<对应布局>(G)),见 nx_pylab.py):
| 函数 | 绑定布局 |
|---|---|
draw_bipartite | bipartite_layout |
draw_circular | circular_layout |
draw_kamada_kawai | kamada_kawai_layout |
draw_planar | planar_layout |
draw_random | random_layout |
draw_spectral | spectral_layout |
draw_spring | spring_layout |
draw_shell | shell_layout |
draw_forceatlas2 | forceatlas2_layout |
2.6 颜色辅助:apply_matplotlib_colors
apply_matplotlib_colors(G, src_attr, dest_attr, map, vmin=None, vmax=None, nodes=True)(nx_pylab.py)读取图中的数值属性,经 colormap 映射为 RGBA 颜色后写回图属性。源码细节:
nodes=True时读取节点属性,否则读取边属性;多重图场景边属性读取使用G.edges(keys=True)。vmin/vmax缺省时自动取属性最小/最大值。- 底层用
mpl.cm.ScalarMappable+set_clim实现映射,并通过nx.set_node_attributes/nx.set_edge_attributes写回。
典型用途:为"按数值着色的自定义绘图"预计算颜色并存入图对象,供后续多次渲染复用。
三、布局算法:networkx.drawing.layout 深度解析
3.1 布局函数的统一约定
layout.py 模块(layout.py)的 __all__ 共 15 个函数。所有布局函数返回 pos 字典(节点 → 坐标元组)。模块 docstring 明确了两个关键约定(源码 L8-L15):
random_layout()的结果范围是[0, scale]的正方形(默认[0, 1]),center会平移整体布局;- 其他布局的结果范围是
[center - scale, center + scale](默认[-1, 1]); - 警告:大多数布局只经过二维测试(
dim=2)。
_process_params(G, center, dim)(layout.py)是所有布局的公共预处理:接受 Graph 或节点列表;center 缺省为原点;center 维度与 dim 不一致时抛出 ValueError。
3.2 各布局算法速查
| 函数 | 算法/原理 | 适用场景 |
|---|---|---|
random_layout | 各坐标在 [0,1) 均匀随机(layout.py) | 基线对比、快速占位 |
circular_layout | 节点均匀分布在圆上(layout.py) | 展示环路、对称结构 |
shell_layout | 按 nlist 分壳层环状分布(layout.py) | 分层/分组结构 |
bipartite_layout | 二部图左右分列(layout.py) | 二部图、投射图 |
spring_layout | Fruchterman-Reingold 力导向(layout.py) | 通用默认首选 |
kamada_kawai_layout | Kamada-Kawai 力导向(基于最短路径距离,layout.py) | 强调图距离结构 |
spectral_layout | 图 Laplacian 特征向量定位(layout.py) | 对称/规则图 |
planar_layout | 无交叉边嵌入(layout.py) | 平面图 |
spiral_layout | 对数螺旋分布(layout.py) | 大环图、长链结构 |
multipartite_layout | 按 subset 属性分层排列(layout.py) | 多部图 |
arf_layout | Arf 力导向,参数 a=1.1、etol=1e-6(layout.py) | 快速大图近似布局 |
forceatlas2_layout | Gephi 同款 ForceAtlas2,max_iter=100、jitter_tolerance=1.0(layout.py) | 社区结构清晰的大图 |
bfs_layout | BFS 分层定位(layout.py) | 树/层次展示 |
rescale_layout / rescale_layout_dict | 缩放坐标到 (-scale, scale)(layout.py) | 坐标归一化 |
3.3 关键参数与可复现性
spring_layout 核心参数(layout.py):
k:节点间最优距离(默认与节点数相关),k=None时自动计算;pos:初始位置字典,可迭代优化;fixed:固定位置的节点列表;iterations:迭代次数,默认 50;weight:边权重属性名,默认"weight";seed:随机种子。
可复现性:random_layout、spring_layout、forceatlas2_layout 等接受 seed 参数(内部经 @np_random_state 装饰器处理,见 layout.py),传入整数种子即可获得确定性布局,这对论文插图、测试复现至关重要。
store_pos_as 参数:random_layout、circular_layout、shell_layout、spectral_layout、spiral_layout、multipartite_layout、bfs_layout 等支持 store_pos_as——非 None 时会把布局结果写入图属性(G.nodes[...][store_pos_as]),函数仍返回 pos 字典(见 layout.py)。
bipartite_layout 的 nodes 参数:传入二部图某一分区的节点集合,两侧节点会沿坐标轴分别排布。
3.4 布局与绘制解耦
布局与绘制是解耦的两步:布局函数只算坐标,绘制函数只消费坐标。这意味着你可以:
- 用任意布局(包括第三方布局)生成
pos; - 微调/裁剪
pos(配合rescale_layout归一化); - 多次调用不同的
draw_networkx_*叠加绘制。
这也是 NetworkX 绘图架构的核心设计——pos 字典是连接布局与渲染的唯一契约。
四、Graphviz 集成:DOT 格式的两种桥接方案
Graphviz 是文档明确推荐的"完全功能"可视化工具之一。NetworkX 提供两条并行通道:pygraphviz(AGraph) 与 pydot,两者功能等价,按依赖偏好二选一即可。
4.1 方案一:nx_agraph(pygraphviz)
模块 __all__(nx_agraph.py):from_agraph、to_agraph、write_dot、read_dot、graphviz_layout、pygraphviz_layout、view_pygraphviz。
基础往返示例(模块 docstring 官方示例):
G = nx.complete_graph(5)
A = nx.nx_agraph.to_agraph(G) # NetworkX → AGraph
H = nx.nx_agraph.from_agraph(A) # AGraph → NetworkX
from_agraph 的类型推断(nx_agraph.py):未指定 create_using 时,按 AGraph 的 is_directed() 与 is_strict() 组合自动推断为 DiGraph/MultiDiGraph/Graph/MultiGraph。转换过程中:
- 图默认属性存入
G.graph_attr(Graphviz 的 graph/node/edge 默认属性分别挂到G.graph["graph"]、G.graph["node"]、G.graph["edge"]); - 节点/边属性原样映射为 NetworkX 属性,节点名转为字符串;
- 非多重图时边名(
e.name)会存为"key"属性(源码 L99-L100)。
graphviz_layout(G, prog="neato", root=None, args="")(nx_agraph.py):调用 Graphviz 布局引擎生成坐标。prog 默认 neato,常用取值还包括 dot(层次布局)、circo、twopi、fdp;args 可透传 Graphviz 命令行参数。返回的 pos 字典可直接喂给 nx.draw。
view_pygraphviz(G, prog="dot"):调用系统默认查看器直接渲染 DOT 文件——无需任何布局计算,是最快的"看一眼"方案。
4.2 方案二:nx_pydot(pydot)
模块 __all__(nx_pydot.py):write_dot、read_dot、graphviz_layout、pydot_layout、to_pydot、from_pydot。
基础往返示例(模块 docstring 官方示例):
G = nx.complete_graph(5)
PG = nx.nx_pydot.to_pydot(G) # NetworkX → pydot.Dot
H = nx.nx_pydot.from_pydot(PG) # pydot.Dot → MultiGraph(默认)
read_dot / write_dot 的文件能力(nx_pydot.py):
write_dot(G, path)把图写成 DOT 文本;文件名以.gz/.bz2结尾时自动压缩(经@open_file装饰器)。read_dot(path)读取 DOT 文件并返回MultiGraph或MultiDiGraph(多重图推断规则:非 strict 的 graph 视为多重图,见from_pydot源码 L121-L130);若文件含多个图,只取第一个。想得到普通Graph需显式转换:G = nx.Graph(nx.nx_pydot.read_dot(path))。
pydot_layout(G, prog="neato", root=None):与 pygraphviz_layout 等价,通过 pydot 驱动 Graphviz 布局。
4.3 两条通道如何选择
- 已安装 pygraphviz → 用
nx_agraph(API 更贴近 AGraph,且支持view_pygraphviz直接预览); - 已安装 pydot → 用
nx_pydot(纯 Python 解析,无编译依赖,安装更省事); - 两者产出的 DOT 文件完全兼容 Graphviz 生态,可进一步交给
dot命令行或 Gephi 等工具。
五、iplotx 与 Hiveplotlib:直接消费 NetworkX 原生对象的现代方案
文档特别强调:这两个库无需文件导出,直接接收 NetworkX 图对象,官方示例可直接复现。
5.1 iplotx:Matplotlib 之上的扩展样式
iplotx 基于 Matplotlib 提供扩展样式绘制。官方示例(见 doc/reference/drawing.rst):
import iplotx as ipx
G = nx.cycle_graph(5, create_using=nx.DiGraph)
layout = nx.circular_layout(G)
ipx.network(G, layout=layout, vertex_facecolor=["tomato", "gold"])
要点:布局仍由 nx.circular_layout 计算(pos 字典),但渲染交给 ipx.network,可通过 vertex_facecolor 等参数逐节点定制颜色。仓库示例 examples/external/plot_iplotx.py 展示了完整用法。
5.2 Hiveplotlib:可复现的蜂巢图
蜂巢图(hive plot)设计思想(源自 doc/reference/drawing.rst):节点按分区变量分布到数条径向轴上,再按排序变量在轴内排序。位置由数据决定而非布局算法,因此结果完全可复现,且图的结构属性直接可读。
官方示例(创建 3 块随机块模型 + 按 pagerank 排序):
from hiveplotlib import HivePlot
p = [[0.3, 0.005, 0.0],
[0.005, 0.3, 0.03],
[0.0, 0.03, 0.3]]
G = nx.stochastic_block_model(sizes=[15, 15, 15], p=p, seed=0)
hp = HivePlot(
graph=G,
partition_variable="block", # 节点按 "block" 属性分轴
sorting_variables="pagerank", # 轴内按 pagerank 排序
node_graph_metrics="pagerank", # 计算节点 pagerank 驱动布局
repeat_axes=True,
)
hp.plot()
node_graph_metrics="pagerank" 体现了两者深度集成:NetworkX 的节点/边度量(如 nx.pagerank)可在布局时实时计算并驱动轴内排序。默认用 Matplotlib 渲染,也可输出到 Bokeh、Plotly、HoloViews;大图可用 Datashader 栅格化。仓库示例见 examples/external/plot_hiveplotlib.py。
六、LaTeX 输出:把 NetworkX 图变成 TikZ 代码
nx_latex.py 模块(nx_latex.py)把图导出为基于 TikZ 的 LaTeX 代码,是论文排版场景的"直通车"。三个核心函数:
to_latex(G, caption=..., as_document=...):返回 LaTeX 字符串(可含 figure 环境);to_latex_raw(G):只返回 TikZ 绘制命令,无 figure 环境;write_latex(G, "filename.tex", caption=..., as_document=...):直接写文件。
基础用法(模块 docstring 官方示例):
from pathlib import Path
import tempfile
tmp_path = Path(tempfile.gettempdir())
G = nx.path_graph(3)
# 生成独立可编译文档
fpath = tmp_path / "just_my_figure.tex"
nx.write_latex(G, fpath, as_document=True)
生成的独立文档结构(完整示例,可直接编译):
\documentclass{report}
\usepackage{tikz}
\usepackage{subcaption}
\begin{document}
\begin{figure}
\begin{tikzpicture}
\draw
(0.0:2) node (0){0}
(120.0:2) node (1){1}
(240.0:2) node (2){2};
\begin{scope}[-]
\draw (0) to (1);
\draw (1) to (2);
\end{scope}
\end{tikzpicture}
\end{figure}
\end{document}
嵌入已有文档:as_document=False 只输出 figure 环境,配合 caption(图题)与 latex_label(\label 引用名,可用 \ref 交叉引用):
nx.write_latex(G, fpath, as_document=False, caption="P3", latex_label="fig1")
多子图(subfigure):to_latex/write_latex 可接收图列表、子图题列表与行数,生成含多个 subfigure 的 figure;每个子图可用 sub_labels 指定 \label。
样式定制机制("The TikZ approach",见 nx_latex.py):
- 绘制选项既可存在图属性中,也可通过
node_options/edge_options字典按节点/边传入 TikZ 选项字符串; - 标签同理:存在节点/边属性,或通过
node_label/edge_label字典按对象传入文本; tikzpicture环境选项(如[scale=2])与默认节点/边选项均可经关键字参数传入;默认节点选项作用于绘制全部节点的单条 path,默认边选项作用于包住每条边的 scope。
官方路线图:模块 docstring 说明未来计划提供 TikZ Graph 接口(含布局算法)。
七、实战工作流:从分析到成图的一条龙方案
结合以上所有能力,一个完整的"分析 → 选型 → 成图"决策流程如下:
- 快速检查阶段:
nx.draw(G)或nx.draw(G, pos=nx.spring_layout(G, seed=0))足以"看个大概",无需额外依赖。 - 结构洞察阶段:按图的类型选择布局——平面图用
planar_layout,社区结构用forceatlas2_layout/spring_layout,层次结构用bfs_layout/multipartite_layout,大环图用spiral_layout;并固定seed保证可复现。 - 精细定制阶段:用
draw_networkx_nodes/draw_networkx_edges/draw_networkx_labels分层渲染,配合apply_matplotlib_colors实现按属性着色;有向图用arrows=True+arrowstyle定制箭头。 - 对外交付阶段:
- 论文排版 →
write_latex(..., as_document=True)生成 TikZ; - DOT 生态(Graphviz 命令行、Gephi)→
nx_pydot.write_dot/nx_agraph.write_dot; - 交互式探索 → 导出 GraphML 交给 Cytoscape(
nx.write_graphml); - 需要专业布局且要 NetworkX 度量参与 →
HivePlot(graph=G, ...)或ipx.network(G, layout=...)。
- 论文排版 →
八、小结
NetworkX 的 drawing 模块是一套"定位克制但功能完整"的绘图设施:draw 系列覆盖从快速预览到精细分层渲染的全过程,layout 模块提供 15 种布局算法与确定性种子支持,nx_agraph/nx_pydot 双通道打通 Graphviz 生态,nx_latex 直达论文排版,iplotx 与 Hiveplotlib 则代表了"直接消费 NetworkX 原生对象"的现代集成方式。理解"NetworkX 主攻分析、可视化交给专业工具"这一官方立场,你就能在快速验证与高质量交付之间做出恰当取舍,让图可视化真正服务于图分析本身。
延伸阅读:绘图相关示例位于 examples/drawing(含节点着色、多图、标签布局等)与 examples/external(iplotx、hiveplotlib、igraph 等外部集成);Matplotlib 绘图与布局的完整函数签名可直接查阅 nx_pylab.py 与 layout.py 的 docstring。
【免费下载链接】networkx
Network Analysis in Python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



