mcpField
N
networkx-graph-analysis

networkx-graph-analysis

github.com/jaechang-hits数据与数据库38470 次安装6 天前更新
代码仓库

关于 networkx-graph-analysis

networkx-graph-analysis 是一份使用 Python NetworkX 创建、操作和分析图的技能指南,面向处理关系数据的研究人员与分析师,涵盖算法、数据格式和可视化。

主要功能

  1. 01无向、有向及多重图结构
  2. 02中心性、路径与连通性分析
  3. 03社区检测与图生成器
  4. 04图数据导入、导出和可视化

适用场景

  1. 01识别社交网络中的关键节点
  2. 02分析生物相互作用网络
  3. 03计算交通网络中的路线
  4. 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-Kawaikamada_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边属性名称在路径/中心性计算中使用加权边
alphapagerank0.850.0-1.0阻尼因子;值越低,分布越均匀
kbetweenness_centralityNoneint在大型图中抽样 k 个节点进行近似计算
max_itereigenvector_centrality100int收敛所需的最大迭代次数
seed生成器/布局Noneint用于确保结果可复现的随机种子
n / p / mER/BA 生成器不固定int/float节点数、边概率、每个新节点的边数
k / pWatts-Strogatz不固定int/float最近邻数量、重连概率
nodetyperead_edgeliststrint、float、str转换节点标识符的类型
edge_attrfrom_pandas_edgelistNone列名要从 DataFrame 中包含的边属性列
formatto_scipy_sparse_array"csc""csr"、"csc"、"coo"稀疏矩阵格式

最佳实践

  1. 始终设置随机种子,确保生成器和布局的结果可复现:在 erdos_renyi_graph() 和 spring_layout() 中都设置 seed=42。

  2. 对大型图使用近似算法:nx.betweenness_centrality(G, k=500) 会抽样 k 个节点,而非检查所有节点对。

  3. 批量加载数据时,优先使用 from_pandas_edgelist,而不是手动循环调用 add_edge——它能妥善处理属性,且速度更快。

  4. 修改子图前先复制:G.subgraph(nodes) 返回只读视图;调用 .copy() 可获得可修改的独立图。

  5. 使用 GraphML 或 GML 进行持久化存储,以保留所有节点/边属性。除非显式处理,否则边列表会丢失元数据。

  6. 显式转换图类型:D.to_undirected()(DiGraph -> Graph),nx.Graph(M)(MultiGraph -> Graph,会合并多重边)。

  7. 导出大型邻接矩阵时使用稀疏矩阵:to_scipy_sparse_array() 比 to_numpy_array() 节省得多的内存。

  8. 反模式——不要使用 nx.info():该函数已弃用;直接使用 G.number_of_nodes()、G.number_of_edges()、nx.density(G)。

  9. 反模式——不要假设节点顺序固定:算法返回结果的顺序可能不同。始终使用节点键索引,而不是位置。

常见示例

示例:最小生成树

提取最小生成树,并与原图进行比较。

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 内部使用的稀疏矩阵操作和数值算法

参考资料

评论

支持 Markdown