NetworkX 图形绘制(Drawing)完全指南:从 Matplotlib 基础绘图到 Graphviz、iplotx 与 LaTeX 生态集成

  • 图计算
  • 数据分析
  • 科学计算

【免费下载链接】networkx

Network Analysis in Python

项目地址: https://gitcode.com/gh_mirrors/ne/networkx
点击查看 免费下载

导读

本文聚焦 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.pyMatplotlib 绘图(draw 系列)matplotlib
layout.py节点布局算法(返回 pos 字典)numpy
nx_agraph.pyGraphviz 桥接(pygraphviz/AGraph)pygraphviz、graphviz
nx_pydot.pyGraphviz 桥接(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))  # 显式指定布局

其内部行为从源码可以拆解出几个关键点:

  1. 画布处理:未传 ax 时使用 plt.gcf() 获取当前 figure,并把 facecolor 设为白色;若无坐标轴则通过 cf.add_axes((0, 0, 1, 1)) 创建全图区坐标轴。
  2. 默认不带标签:draw 是"简洁模式",默认不画节点/边标签、不显示坐标轴刻度(绘制后调用 ax.set_axis_off())。
  3. 标签开关联动:with_labels 默认值由 "labels" in kwds 推断——即只要你传入了 labels 字典,就会自动开启标签绘制(见源码 L1175-L1176)。
  4. 命名冲突警告: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):

参数默认值说明
posNone(自动 spring)节点位置字典,键为节点、值为二维坐标
arrowsNoneNone:有向图用 FancyArrowPatch 画箭头、无向图用 LineCollection(更快);True 强制画箭头;False 全部用 LineCollection
arrowstyle'-|>'(有向图)箭头样式,无向图默认 '-',详见 matplotlib.patches.ArrowStyle
arrowsize10箭头长度与宽度;可传列表分别设置
with_labelsTrue是否绘制节点标签
nodelist / edgelistlist(G) / list(G.edges())只绘制指定节点/边
node_size300节点大小,数组需与 nodelist 等长
node_color'#1f78b4'节点颜色;数值序列会被 cmap/vmin/vmax 映射
node_shape'o'节点形状,取自 'so^>v<dph8'
alphaNone节点与边透明度
cmap / vmin / vmaxNone节点颜色映射的 colormap 与数值范围
width1.0边线宽(可传数组逐边设置)
edge_color'k'边颜色,可用 edge_cmap/edge_vmin/edge_vmax 映射
stylesolid边线型:'-'、'--'、'-.'、':'
font_size / font_color / font_weight / font_family12(边 10)/ 'k' / normal / sans-serif标签文本样式
labelNone图例标签
hide_ticksTrue隐藏坐标轴刻度与刻度标签;设为 False 恢复 pyplot 默认
axNone指定 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_bipartitebipartite_layout
draw_circularcircular_layout
draw_kamada_kawaikamada_kawai_layout
draw_planarplanar_layout
draw_randomrandom_layout
draw_spectralspectral_layout
draw_springspring_layout
draw_shellshell_layout
draw_forceatlas2forceatlas2_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_layoutFruchterman-Reingold 力导向(layout.py)通用默认首选
kamada_kawai_layoutKamada-Kawai 力导向(基于最短路径距离,layout.py)强调图距离结构
spectral_layout图 Laplacian 特征向量定位(layout.py)对称/规则图
planar_layout无交叉边嵌入(layout.py)平面图
spiral_layout对数螺旋分布(layout.py)大环图、长链结构
multipartite_layout按 subset 属性分层排列(layout.py)多部图
arf_layoutArf 力导向,参数 a=1.1、etol=1e-6(layout.py)快速大图近似布局
forceatlas2_layoutGephi 同款 ForceAtlas2,max_iter=100、jitter_tolerance=1.0(layout.py)社区结构清晰的大图
bfs_layoutBFS 分层定位(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 布局与绘制解耦

布局与绘制是解耦的两步:布局函数只算坐标,绘制函数只消费坐标。这意味着你可以:

  1. 用任意布局(包括第三方布局)生成 pos;
  2. 微调/裁剪 pos(配合 rescale_layout 归一化);
  3. 多次调用不同的 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 接口(含布局算法)。


七、实战工作流:从分析到成图的一条龙方案

结合以上所有能力,一个完整的"分析 → 选型 → 成图"决策流程如下:

  1. 快速检查阶段:nx.draw(G) 或 nx.draw(G, pos=nx.spring_layout(G, seed=0)) 足以"看个大概",无需额外依赖。
  2. 结构洞察阶段:按图的类型选择布局——平面图用 planar_layout,社区结构用 forceatlas2_layout/spring_layout,层次结构用 bfs_layout/multipartite_layout,大环图用 spiral_layout;并固定 seed 保证可复现。
  3. 精细定制阶段:用 draw_networkx_nodes / draw_networkx_edges / draw_networkx_labels 分层渲染,配合 apply_matplotlib_colors 实现按属性着色;有向图用 arrows=True + arrowstyle 定制箭头。
  4. 对外交付阶段:
    • 论文排版 → 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

项目地址: https://gitcode.com/gh_mirrors/ne/networkx
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值