生物医学网络科学Biomedical Network Science
Example09 / 13

三节点子图普查(triad census)与显著性谱

所属专题
生物分子网络与拓扑特征
下载
Notebook · .py

networkx 的 triadic_census 按 MAN 编码统计 16 类三元组(含不连通的 003、012、102); 其中 030T 即前馈环,021D 为“一个调控者调两个靶”,021U 为“两个调控者共调一个靶”。 模拟一个嵌入了前馈环与单输入模块的调控网络,用保持入度/出度的边交换生成 50 个随机网络, 对 13 类连通三元组计算 Z 分数与显著性谱 SP = Z / ||Z||。 输出解读:030T(FFL)的 Z 显著为正;正式分析应使用更多随机网络并报告经验 p 值。

Output输出图

三节点子图普查(triad census)与显著性谱:输出图 1

Output文字输出

021D  真实   454  随机均值   458.2  Z =   -0.4  SP = -0.07
021U  真实   419  随机均值   422.3  Z =   -0.3  SP = -0.06
021C  真实   839  随机均值   828.8  Z =    0.5  SP =  0.10
111D  真实     1  随机均值    15.6  Z =   -1.8  SP = -0.34
111U  真实     5  随机均值    15.4  Z =   -1.0  SP = -0.18
030T  真实    33  随机均值    15.5  Z =    4.5  SP =  0.85
030C  真实     2  随机均值     4.4  Z =   -1.0  SP = -0.19
120C  真实     1  随机均值     0.3  Z =    1.3  SP =  0.24

Code代码

# networkx 的 triadic_census 按 MAN 编码统计 16 类三元组(含不连通的 003、012、102);
# 其中 030T 即前馈环,021D 为“一个调控者调两个靶”,021U 为“两个调控者共调一个靶”。
# 模拟一个嵌入了前馈环与单输入模块的调控网络,用保持入度/出度的边交换生成 50 个随机网络,
# 对 13 类连通三元组计算 Z 分数与显著性谱 SP = Z / ||Z||。
# 输出解读:030T(FFL)的 Z 显著为正;正式分析应使用更多随机网络并报告经验 p 值。
import numpy as np
import networkx as nx

rng = np.random.default_rng(7)
D = nx.gnm_random_graph(150, 260, directed=True, seed=7)   # 模拟数据,仅用于演示方法
for _ in range(25):
    x, y, z = rng.choice(150, 3, replace=False); D.add_edges_from([(x, y), (y, z), (x, z)])
for _ in range(5):                                           # 单输入模块:一个 TF 调 6 个靶
    tf = int(rng.integers(150)); D.add_edges_from((tf, int(g)) for g in rng.choice(150, 6, replace=False) if g != tf)
D.remove_edges_from(list(nx.selfloop_edges(D)))

def shuffle(D, n_swap, rng):
    D = D.copy(); edges = list(D.edges()); done = 0; tries = 0
    while done < n_swap and tries < 50 * n_swap:
        tries += 1
        i, j = rng.integers(len(edges), size=2)
        (a, b), (c, d) = edges[i], edges[j]
        if len({a, b, c, d}) < 4 or D.has_edge(a, d) or D.has_edge(c, b):
            continue
        D.remove_edges_from([(a, b), (c, d)]); D.add_edges_from([(a, d), (c, b)])
        edges[i], edges[j] = (a, d), (c, b); done += 1
    return D

connected = ["021D", "021U", "021C", "111D", "111U", "030T", "030C",
             "201", "120D", "120U", "120C", "210", "300"]
real = nx.triadic_census(D)
null = np.array([[nx.triadic_census(shuffle(D, 5 * D.number_of_edges(), rng))[c] for c in connected]
                 for _ in range(50)])
Z = (np.array([real[c] for c in connected]) - null.mean(0)) / (null.std(0) + 1e-9)
SP = Z / np.linalg.norm(Z)
for c, r, m, z, sp in zip(connected, [real[c] for c in connected], null.mean(0), Z, SP):
    if r > 0 or m > 0.5:
        print(f"{c:5s} 真实 {r:5d}  随机均值 {m:7.1f}  Z = {z:6.1f}  SP = {sp:5.2f}")

import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(6.4, 4.2))
ax.bar(connected, SP, color=["C3" if c == "030T" else "0.6" for c in connected])
ax.axhline(0, color="k", lw=0.8)
ax.set_xlabel("connected triad type (MAN code)"); ax.set_ylabel("significance profile SP = Z / ||Z||")
ax.tick_params(axis="x", rotation=45)
ax.set_title("Triad significance profile (red: 030T = feed-forward loop)")
plt.tight_layout(); plt.show()

Run在浏览器中运行

首次加载 Python 环境约需 20–40 秒;可以修改参数后重新运行。

三节点子图普查(triad census)与显著性谱