关于 networkx-graph-analysis
networkx-graph-analysis 是一份使用 Python NetworkX 创建、操作和分析图的技能指南,面向处理关系数据的研究人员与分析师,涵盖算法、数据格式和可视化。
主要功能
- 01无向、有向及多重图结构
- 02中心性、路径与连通性分析
- 03社区检测与图生成器
- 04图数据导入、导出和可视化
适用场景
- 01识别社交网络中的关键节点
- 02分析生物相互作用网络
- 03计算交通网络中的路线
- 04为模拟生成合成图
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill networkx-graph-analysis安装后在 Claude Code 中输入/networkx-graph-analysis确认已加载。
附带文件references/algorithms_generators.mdreferences/io_visualization.md
详细介绍
NetworkX 图分析
概述
NetworkX 是一个用于创建、操作和分析复杂网络与图的 Python 库。它提供无向图、有向图和多重边图的数据结构,以及全面的图算法、生成器和 I/O 工具集。处理社交网络、生物相互作用网络、交通系统、引用图或任何涉及实体两两关系的领域中的关系数据时,可使用 NetworkX。
适用场景
- 分析蛋白质-蛋白质相互作用网络、基因调控网络或代谢通路
- 计算中心性指标(度、介数、PageRank),以识别重要节点
- 在交通或通信网络中查找最短路径或最优路线
- 在社交网络或共表达数据中检测社区或聚类
- 生成合成网络(无标度、小世界、随机网络),用于模拟或零模型
- 以标准格式(GraphML、GML、边列表、JSON)读写图数据
- 使用节点/边属性映射可视化网络拓扑
- 检查图属性:连通性、平面性、同构性、DAG 结构
- 对于速度至关重要的大规模图(100K+ 个节点),请改用
igraph或graph-tool - 对于拥有数十亿条边的图或 GPU 加速分析,请使用带有 OpenMP 的
graph-tool或cuGraph - 对于图神经网络和图上的深度学习,请使用
torch-geometric-graph-neural-networks
前置条件
- Python 包:
networkx、matplotlib、scipy、pandas、numpy - 可选项:
pydot或pygraphviz(Graphviz 布局)
pip install networkx matplotlib scipy pandas numpy
快速开始
import networkx as nx
# Create a graph and add edges with weights
G = nx.karate_club_graph()
print(f"Nodes: {G.number_of_nodes()}, Edges: {G.number_of_edges()}")
# Nodes: 34, Edges: 78
# Compute centrality and find most central node
bc = nx.betweenness_centrality(G)
top_node = max(bc, key=bc.get)
print(f"Most central node: {top_node}, betweenness: {bc[top_node]:.3f}")
# Detect communities
from networkx.algorithms import community
comms = community.greedy_modularity_communities(G)
print(f"Communities found: {len(comms)}")
核心 API
模块 1:图的创建与类型
import networkx as nx
# Undirected graph (most common)
G = nx.Graph()
G.add_node("protein_A", type="kinase", weight=1.5)
G.add_nodes_from(["protein_B", "protein_C"])
G.add_edge("protein_A", "protein_B", weight=0.9, interaction="phosphorylation")
G.add_edges_from([("protein_B", "protein_C"), ("protein_A", "protein_C")])
print(f"Nodes: {G.number_of_nodes()}, Edges: {G.number_of_edges()}")
# Nodes: 3, Edges: 3
# Directed graph (gene regulation, citations)
D = nx.DiGraph()
D.add_edges_from([("TF1", "geneA"), ("TF1", "geneB"), ("TF2", "geneA")])
print(f"TF1 out-degree: {D.out_degree('TF1')}") # 2
# MultiGraph (multiple relationship types between same nodes)
M = nx.MultiGraph()
M.add_edge("A", "B", key="binding", affinity=0.8)
M.add_edge("A", "B", key="regulation", effect="inhibition")
print(f"Edges between A-B: {M.number_of_edges('A', 'B')}") # 2
模块 2:节点与边操作
import networkx as nx
G = nx.karate_club_graph()
# Query structure
print(f"Degree of node 0: {G.degree(0)}")
print(f"Neighbors of node 0: {list(G.neighbors(0))[:5]}")
print(f"Has edge 0-1: {G.has_edge(0, 1)}")
# Set and get attributes
G.nodes[0]["role"] = "instructor"
nx.set_node_attributes(G, {0: "high", 33: "high"}, "importance")
G[0][1]["weight"] = 0.95
# Iterate with data
for u, v, data in G.edges(data=True):
if "weight" in data:
print(f" Edge {u}-{v}: weight={data['weight']}")
break
# Subgraphs (returns read-only view; use .copy() for mutable)
H = G.subgraph([0, 1, 2, 3, 4, 5]).copy()
print(f"Subgraph: {H.number_of_nodes()} nodes, {H.number_of_edges()} edges")
模块 3:图分析(中心性)
import networkx as nx
G = nx.karate_club_graph()
degree_c = nx.degree_centrality(G)
between_c = nx.betweenness_centrality(G, weight="weight")
# For large graphs, approximate: nx.betweenness_centrality(G, k=100)
close_c = nx.closeness_centrality(G)
eigen_c = nx.eigenvector_centrality(G, max_iter=1000)
pr = nx.pagerank(G, alpha=0.85)
# Compare top nodes across measures
for name, metric in [("Degree", degree_c), ("Betweenness", between_c),
("Closeness", close_c), ("PageRank", pr)]:
top = max(metric, key=metric.get)
print(f"{name:12s}: top node={top}, score={metric[top]:.4f}")
模块 4:路径与连通性
import networkx as nx
G = nx.karate_club_graph()
# Shortest path
path = nx.shortest_path(G, source=0, target=33)
length = nx.shortest_path_length(G, source=0, target=33)
print(f"Shortest path 0->33: {path} (length {length})")
print(f"Average shortest path length: {nx.average_shortest_path_length(G):.3f}")
# Connected components
print(f"Connected: {nx.is_connected(G)}")
components = list(nx.connected_components(G))
print(f"Components: {len(components)}, largest: {len(max(components, key=len))}")
# For directed graphs: strong/weak connectivity
D = nx.DiGraph([(0,1),(1,2),(2,0),(3,4)])
print(f"Strongly connected: {list(nx.strongly_connected_components(D))}")
# Connectivity measures
print(f"Node connectivity: {nx.node_connectivity(G)}")
print(f"Edge connectivity: {nx.edge_connectivity(G)}")
模块 5:社区检测
将网络划分为连接紧密的群组。
import networkx as nx
from networkx.algorithms import community
import itertools
G = nx.karate_club_graph()
# Greedy modularity maximization
comms_greedy = community.greedy_modularity_communities(G)
mod_score = community.modularity(G, comms_greedy)
print(f"Greedy: {len(comms_greedy)} communities, modularity={mod_score:.4f}")
# Label propagation (fast, non-deterministic)
comms_lpa = community.label_propagation_communities(G)
print(f"Label propagation: {len(list(comms_lpa))} communities")
# Girvan-Newman (hierarchical, edge betweenness removal)
gn = community.girvan_newman(G)
# Get first level of partition
first_level = next(gn)
print(f"Girvan-Newman first split: {len(first_level)} groups")
print(f" Sizes: {[len(c) for c in first_level]}")
模块 6:I/O 与序列化
import networkx as nx
import pandas as pd
import json
G = nx.karate_club_graph()
# Edge list (simple text format)
nx.write_edgelist(G, "karate.edgelist")
G_loaded = nx.read_edgelist("karate.edgelist", nodetype=int)
# GraphML (preserves all attributes, XML-based)
nx.write_graphml(G, "karate.graphml")
G_xml = nx.read_graphml("karate.graphml")
# JSON (node-link format, web-friendly for d3.js)
data = nx.node_link_data(G)
with open("karate.json", "w") as f:
json.dump(data, f)
# Pandas integration
df = pd.DataFrame({"source": [1,2,3], "target": [2,3,4], "weight": [0.5,1.0,0.75]})
G_pd = nx.from_pandas_edgelist(df, "source", "target", edge_attr="weight")
df_out = nx.to_pandas_edgelist(G_pd)
print(f"Pandas round-trip: {len(df_out)} edges")
# NumPy/SciPy matrices
A = nx.to_numpy_array(G)
print(f"Adjacency matrix shape: {A.shape}")
A_sparse = nx.to_scipy_sparse_array(G, format="csr") # Memory-efficient
模块 7:可视化
import networkx as nx
import matplotlib.pyplot as plt
G = nx.karate_club_graph()
pos = nx.spring_layout(G, seed=42)
# Color by degree, size by betweenness centrality
bc = nx.betweenness_centrality(G)
fig, ax = plt.subplots(figsize=(10, 8))
nx.draw(G, pos=pos, ax=ax,
node_color=[G.degree(n) for n in G.nodes()], cmap=plt.cm.viridis,
node_size=[3000 * bc[n] + 100 for n in G.nodes()],
edge_color="gray", alpha=0.8, with_labels=True, font_size=8)
plt.tight_layout()
plt.savefig("network.png", dpi=300, bbox_inches="tight")
plt.savefig("network.pdf", bbox_inches="tight") # Vector format
print("Saved network.png and network.pdf")
模块 8:生成器
import networkx as nx
# Erdos-Renyi random graph: n nodes, edge probability p
G_er = nx.erdos_renyi_graph(n=200, p=0.05, seed=42)
print(f"ER: {G_er.number_of_nodes()} nodes, {G_er.number_of_edges()} edges")
# Barabasi-Albert scale-free (power-law degree distribution)
G_ba = nx.barabasi_albert_graph(n=200, m=3, seed=42)
# Watts-Strogatz small-world
G_ws = nx.watts_strogatz_graph(n=200, k=6, p=0.1, seed=42)
print(f"WS clustering: {nx.average_clustering(G_ws):.3f}")
# Stochastic block model (community structure)
sizes, probs = [50, 50, 50], [[0.25,0.05,0.02],[0.05,0.35,0.07],[0.02,0.07,0.40]]
G_sbm = nx.stochastic_block_model(sizes, probs, seed=42)
# Built-in datasets and classic graphs
G_karate = nx.karate_club_graph() # Zachary's karate club
G_grid = nx.grid_2d_graph(5, 7) # 2D lattice
G_tree = nx.random_tree(n=50, seed=42) # Random tree
G_geo = nx.random_geometric_graph(n=100, radius=0.2, seed=42)
# See references/algorithms_generators.md for full generator catalog
核心概念
图类型
| 类 | 有向 | 多重边 | 自环 | 用例 |
|---|---|---|---|---|
Graph | 否 | 否 | 是 | 无向网络:社交网络、PPI |
DiGraph | 是 | 否 | 是 | 基因调控、引用、网页 |
MultiGraph | 否 | 是 | 是 | 多种关系类型 |
MultiDiGraph | 是 | 是 | 是 | 含路线的交通网络 |
属性模式
属性以字典形式存储在图、节点和边各自的层级:
import networkx as nx
G = nx.Graph(name="example") # Graph-level attribute
G.add_node(1, label="hub", weight=1.5) # Node attributes
G.add_edge(1, 2, weight=0.8, type="ppi") # Edge attributes
# Bulk set/get
nx.set_node_attributes(G, {1: "red", 2: "blue"}, "color")
colors = nx.get_node_attributes(G, "color") # {1: 'red', 2: 'blue'}
布局算法
| 布局 | 函数 | 最适用场景 |
|---|---|---|
| 弹簧(力导向) | spring_layout(G, seed=42) | 通用网络 |
| 圆形 | circular_layout(G) | 规则图、环 |
| Kamada-Kawai | kamada_kawai_layout(G) | 中小型网络 |
| 谱布局 | spectral_layout(G) | 突出显示聚类 |
| 壳层(同心圆) | shell_layout(G, nlist=[[...],[...]]) | 分层/层级结构 |
| 平面 | planar_layout(G) | 仅适用于平面图 |
常见工作流
工作流 1:社交网络分析
目标:识别有影响力的参与者、检测社区并进行可视化。
import networkx as nx
import matplotlib.pyplot as plt
from networkx.algorithms import community
# Step 1: Load network and basic stats
G = nx.karate_club_graph()
print(f"Network: {G.number_of_nodes()} actors, {G.number_of_edges()} ties")
print(f"Density: {nx.density(G):.4f}, Clustering: {nx.average_clustering(G):.4f}")
# Step 2: Identify influential nodes
bc = nx.betweenness_centrality(G)
top_bc = sorted(bc.items(), key=lambda x: x[1], reverse=True)[:5]
print("Top 5 by betweenness:", [(n, f"{s:.3f}") for n, s in top_bc])
# Step 3: Detect communities
comms = community.greedy_modularity_communities(G)
print(f"Communities: {len(comms)}, modularity: {community.modularity(G, comms):.4f}")
# Step 4: Visualize with community coloring
pos = nx.spring_layout(G, seed=42)
fig, ax = plt.subplots(figsize=(10, 8))
for i, comm in enumerate(comms):
nx.draw_networkx_nodes(G, pos, nodelist=list(comm), ax=ax,
node_color=[plt.cm.Set2(i)]*len(comm), node_size=400)
nx.draw_networkx_edges(G, pos, ax=ax, alpha=0.3)
nx.draw_networkx_labels(G, pos, ax=ax, font_size=8)
plt.axis("off")
plt.tight_layout()
plt.savefig("social_network_analysis.png", dpi=300, bbox_inches="tight")
print("Saved social_network_analysis.png")
工作流 2:生物相互作用网络
目标:根据表格数据构建 PPI 网络、分析拓扑并识别枢纽蛋白。
import networkx as nx
import pandas as pd
# Step 1: Load interaction data from DataFrame
interactions = pd.DataFrame({
"protein_a": ["TP53","TP53","BRCA1","BRCA1","MDM2","ATM","ATM","CHEK2","RB1","CDK2"],
"protein_b": ["MDM2","BRCA1","ATM","CHEK2","RB1","CHEK2","BRCA2","CDC25A","CDK2","CCNA2"],
"score": [0.99, 0.95, 0.92, 0.88, 0.91, 0.97, 0.85, 0.90, 0.87, 0.93]
})
G = nx.from_pandas_edgelist(interactions, "protein_a", "protein_b",
edge_attr="score")
print(f"PPI network: {G.number_of_nodes()} proteins, {G.number_of_edges()} interactions")
# Step 2: Network statistics
print(f"Connected: {nx.is_connected(G)}")
print(f"Diameter: {nx.diameter(G)}")
print(f"Avg path length: {nx.average_shortest_path_length(G):.2f}")
print(f"Transitivity: {nx.transitivity(G):.4f}")
# Step 3: Hub identification (multiple centrality measures)
degree_c = nx.degree_centrality(G)
between_c = nx.betweenness_centrality(G)
close_c = nx.closeness_centrality(G)
results = pd.DataFrame({
"protein": list(G.nodes()),
"degree_centrality": [degree_c[n] for n in G.nodes()],
"betweenness": [between_c[n] for n in G.nodes()],
"closeness": [close_c[n] for n in G.nodes()],
}).sort_values("betweenness", ascending=False)
print("\nHub proteins:")
print(results.head(5).to_string(index=False))
# Step 4: Export for downstream analysis
nx.write_graphml(G, "ppi_network.graphml")
results.to_csv("protein_centrality.csv", index=False)
print("Exported ppi_network.graphml and protein_centrality.csv")
关键参数
| 参数 | 模块 | 默认值 | 范围 / 选项 | 作用 |
|---|---|---|---|---|
weight | 路径/中心性 | None | 边属性名称 | 在路径/中心性计算中使用加权边 |
alpha | pagerank | 0.85 | 0.0-1.0 | 阻尼因子;值越低,分布越均匀 |
k | betweenness_centrality | None | int | 在大型图中抽样 k 个节点进行近似计算 |
max_iter | eigenvector_centrality | 100 | int | 收敛所需的最大迭代次数 |
seed | 生成器/布局 | None | int | 用于确保结果可复现的随机种子 |
n / p / m | ER/BA 生成器 | 不固定 | int/float | 节点数、边概率、每个新节点的边数 |
k / p | Watts-Strogatz | 不固定 | int/float | 最近邻数量、重连概率 |
nodetype | read_edgelist | str | int、float、str | 转换节点标识符的类型 |
edge_attr | from_pandas_edgelist | None | 列名 | 要从 DataFrame 中包含的边属性列 |
format | to_scipy_sparse_array | "csc" | "csr"、"csc"、"coo" | 稀疏矩阵格式 |
最佳实践
-
始终设置随机种子,确保生成器和布局的结果可复现:在
erdos_renyi_graph()和spring_layout()中都设置seed=42。 -
对大型图使用近似算法:
nx.betweenness_centrality(G, k=500)会抽样 k 个节点,而非检查所有节点对。 -
批量加载数据时,优先使用
from_pandas_edgelist,而不是手动循环调用add_edge——它能妥善处理属性,且速度更快。 -
修改子图前先复制:
G.subgraph(nodes)返回只读视图;调用.copy()可获得可修改的独立图。 -
使用 GraphML 或 GML 进行持久化存储,以保留所有节点/边属性。除非显式处理,否则边列表会丢失元数据。
-
显式转换图类型:
D.to_undirected()(DiGraph -> Graph),nx.Graph(M)(MultiGraph -> Graph,会合并多重边)。 -
导出大型邻接矩阵时使用稀疏矩阵:
to_scipy_sparse_array()比to_numpy_array()节省得多的内存。 -
反模式——不要使用
nx.info():该函数已弃用;直接使用G.number_of_nodes()、G.number_of_edges()、nx.density(G)。 -
反模式——不要假设节点顺序固定:算法返回结果的顺序可能不同。始终使用节点键索引,而不是位置。
常见示例
示例:最小生成树
提取最小生成树,并与原图进行比较。
import networkx as nx
# Create weighted graph
G = nx.erdos_renyi_graph(50, 0.15, seed=42)
for u, v in G.edges():
G[u][v]["weight"] = round(nx.utils.py_random_state(42).random(), 2)
mst = nx.minimum_spanning_tree(G, weight="weight")
print(f"Original: {G.number_of_edges()} edges")
print(f"MST: {mst.number_of_edges()} edges")
total_weight = sum(d["weight"] for _, _, d in mst.edges(data=True))
print(f"MST total weight: {total_weight:.2f}")
示例:图着色与团
查找团并计算图着色。
import networkx as nx
G = nx.karate_club_graph()
# Find all maximal cliques
cliques = list(nx.find_cliques(G))
print(f"Maximal cliques: {len(cliques)}")
largest_clique = max(cliques, key=len)
print(f"Largest clique size: {len(largest_clique)}, nodes: {largest_clique}")
# Greedy graph coloring
coloring = nx.greedy_color(G, strategy="largest_first")
n_colors = max(coloring.values()) + 1
print(f"Chromatic number (greedy upper bound): {n_colors}")
示例:DAG 与拓扑排序
构建有向无环图并查找执行顺序。
import networkx as nx
# Task dependency DAG
D = nx.DiGraph()
D.add_edges_from([
("download_data", "preprocess"),
("download_data", "validate"),
("preprocess", "analyze"),
("validate", "analyze"),
("analyze", "visualize"),
("analyze", "report"),
("visualize", "report"),
])
print(f"Is DAG: {nx.is_directed_acyclic_graph(D)}")
order = list(nx.topological_sort(D))
print(f"Execution order: {order}")
# Find all paths from start to end
paths = list(nx.all_simple_paths(D, "download_data", "report"))
print(f"Paths to report: {len(paths)}")
for p in paths:
print(f" {' -> '.join(p)}")
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
NetworkXError: Graph is not connected | 算法要求图是连通图 | 提取最大连通分量:G.subgraph(max(nx.connected_components(G), key=len)).copy() |
PowerIterationFailedConvergence | 特征向量/PageRank 未收敛 | 增大 max_iter(例如,设为 1000),或检查是否存在非连通分量 |
| 中心性计算非常缓慢 | 大型图上的复杂度为 O(n*m) | 使用 k 参数进行采样:betweenness_centrality(G, k=500) |
nx.NetworkXNotImplemented | 算法不适用于该图类型 | 转换图类型:G.to_undirected() 或 G.to_directed() |
| 大型图导致内存错误 | 邻接矩阵是稠密矩阵 | 使用 to_scipy_sparse_array() 替代 to_numpy_array() |
| 从文件读取的节点 ID 被视为字符串 | read_edgelist 默认使用 str | 传入 nodetype=int:nx.read_edgelist(f, nodetype=int) |
| 社区检测返回冻结集合 | 社区的正常返回类型 | 转换:[list(c) for c in communities] |
| 生成的图中存在自环 | 配置模型允许自环 | 移除:G.remove_edges_from(nx.selfloop_edges(G)) |
| 可视化过于杂乱 | 节点/边过多 | 筛选子图、调整 alpha、增大图像尺寸,或使用交互式工具(Plotly、PyVis) |
附带资源
从原始条目迁移(主文件为 STUB:436 行,5 个参考文件共 2,014 行,主文件/总计 = 17.8%)。
references/algorithms_generators.md
涵盖:遍历(DFS/BFS)、环、团、图着色、同构、匹配/覆盖、树算法(MST 的变体)的详细算法参数。完整的生成器目录:经典图、格/网格、树、二分图、度序列、图操作(并集、复合、补图、乘积)。 已内联迁移:核心算法(中心性、路径、连通性、社区、流)-> 核心 API 第 3-5 模块。核心生成器(ER、BA、WS、SBM)-> 第 8 模块。 未纳入:A* 启发式定制、Bellman-Ford 负权重——请查阅官方文档。
原始文件处理方式:
algorithms.md(383 行):主要算法已迁移至核心 API 第 3-5 模块 + 使用示例。其余内容(遍历、团、着色、同构、匹配、环、树)-> 本参考文件。generators.md(378 行):核心生成器已迁移至第 8 模块。完整目录(经典图、格、树、二分图、度序列、运算符)-> 本参考文件。
references/io_visualization.md
涵盖:所有 I/O 格式(邻接表、GEXF、Pajek、LEDA、Cytoscape JSON、DOT/Graphviz、Matrix Market、CSV、数据库/SQL、gzip 压缩)。格式选择指南。高级可视化:Plotly 交互式可视化、PyVis HTML、Graphviz 布局、3D 网络、二分图布局、社区着色、子图高亮、多面板图、边标签、有向箭头。
已内联迁移:核心 I/O(边列表、GraphML、JSON、pandas、NumPy/SciPy)-> 第 6 模块。基础 matplotlib -> 第 7 模块。
未纳入:write_gpickle/read_gpickle(已弃用)、read_shp/write_shp(已在 NetworkX 3.0 中移除;请使用 geopandas)。
原始文件处理方式:
io.md(441 行):核心格式已迁移至第 6 模块。其余格式及格式选择指南 -> 本参考文件。visualization.md(529 行):基础 matplotlib 已迁移至第 7 模块。高级技术(Plotly、PyVis、3D、二分图、社区着色)-> 本参考文件。
已完全整合的原始文件
graph-basics.md(283 行):已完全整合到主 SKILL.md 中。图类型 -> 关键概念。节点/边操作、属性、子图 -> 核心 API 第 1-2 模块。诊断 -> 常见工作流。内存/浮点数注意事项 -> 最佳实践 + 故障排除。未纳入:nx.info()(已弃用)。
相关技能
- torch-geometric-graph-neural-networks -- 用于图结构数据的节点/图分类和链接预测的图神经网络(GCN、GAT、GraphSAGE)
- matplotlib-scientific-plotting -- 超越 NetworkX 内置
nx.draw的高级图表自定义 - plotly-interactive-plots -- 支持悬停、缩放和平移的交互式网络图
- pandas(计划中)-- 在构建图之前用于准备边/节点数据的 DataFrame 操作
- scipy(计划中)-- NetworkX 内部使用的稀疏矩阵操作和数值算法
参考资料
- NetworkX 文档 -- 官方文档和 API 参考
- NetworkX 教程 -- 官方入门指南
- NetworkX GitHub -- 源代码和问题跟踪器
- NetworkX 示例库 -- 包含可视化的示例集
- Hagberg, A., Schult, D., & Swart, P. (2008). 使用 NetworkX 探索网络结构、动态特性和功能。SciPy 2008。