跳转至

403_多组学数据可视化策略


一句话说明

多组学可视化就是把多层次的高维数据用图表讲清楚,让审稿人一眼看懂你的故事。


核心知识点

常用图表类型与适用场景

图表类型适用场景工具
热图(Heatmap)展示多样本多特征的整体模式ComplexHeatmap, seaborn
桑基图(Sankey)展示组学层次间的关系流向plotly, ggalluvial
网络图(Network)展示特征间关联关系igraph, Cytoscape
UMAP/tSNE高维数据降维可视化umap-learn
气泡图展示多维度富集结果ggplot2
瀑布图(Waterfall)展示排序后的变化量ggplot2
森林图(Forest plot)展示多个变量的效应量forestplot

配色原则

  • 连续变量:渐变色(viridis, RdBu)—— 不用彩虹色!
  • 分类变量:定性颜色板(Set1, Paired)
  • 色盲友好:ColorBrewer中的colorblind-safe方案
  • 双向变化:红蓝分歧色(上调=红,下调=蓝)

实战代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

np.random.seed(42)

# ========== 1. 多组学热图(ComplexHeatmap风格) ==========
# 生成模拟数据
n_samples = 30  # 样本数
n_features = 50  # 特征数

# 转录组数据(Z-score归一化后的表达量)
rna_matrix = np.random.randn(n_features, n_samples)

# 样本分组信息(用于热图注释)
sample_groups = pd.Categorical(
    ["Control"] * 10 + ["Treatment_A"] * 10 + ["Treatment_B"] * 10
)

# 创建带注释的热图
fig, (ax_anno, ax_heat) = plt.subplots(
    2, 1, figsize=(14, 8),
    gridspec_kw={"height_ratios": [0.5, 10]}  # 注释行占1/20高度
)

# 顶部注释(样本分组颜色条)
colors = {"Control": "#2196F3", "Treatment_A": "#F44336", "Treatment_B": "#4CAF50"}
anno_colors = [colors[g] for g in sample_groups]
ax_anno.imshow(
    [range(n_samples)],  # 只是一行,用来显示颜色
    aspect="auto",
    cmap=None
)
for i, (color, group) in enumerate(zip(anno_colors, sample_groups)):
    ax_anno.add_patch(plt.Rectangle((i-0.5, -0.5), 1, 1, color=color))  # 画彩色方块
ax_anno.set_xlim(-0.5, n_samples - 0.5)
ax_anno.set_xticks([])
ax_anno.set_yticks([0])
ax_anno.set_yticklabels(["Group"])

# 主热图
im = ax_heat.imshow(
    rna_matrix, 
    aspect="auto",
    cmap="RdBu_r",  # 红蓝分歧色:红=高表达,蓝=低表达
    vmin=-3, vmax=3  # 固定颜色范围,确保跨图比较一致
)
ax_heat.set_xticks([])
ax_heat.set_yticks(range(0, n_features, 10))
ax_heat.set_yticklabels([f"Feature_{i}" for i in range(0, n_features, 10)])

plt.colorbar(im, ax=ax_heat, label="Z-score")
plt.suptitle("Multi-omics Heatmap", fontsize=14, fontweight="bold")
plt.tight_layout()
plt.savefig("multiomics_heatmap.png", dpi=150, bbox_inches="tight")
print("热图已保存")

# ========== 2. 气泡图(通路富集结果) ==========
# 模拟富集分析结果
pathways = {
    "Glycolysis": {"p_value": 0.001, "odds_ratio": 3.2, "gene_count": 25},
    "TCA cycle": {"p_value": 0.005, "odds_ratio": 2.8, "gene_count": 18},
    "Fatty acid oxidation": {"p_value": 0.01, "odds_ratio": 2.1, "gene_count": 30},
    "DNA repair": {"p_value": 0.02, "odds_ratio": 1.8, "gene_count": 15},
    "Cell cycle": {"p_value": 0.04, "odds_ratio": 1.5, "gene_count": 40},
}

df_enrich = pd.DataFrame(pathways).T.reset_index()
df_enrich.columns = ["Pathway", "p_value", "odds_ratio", "gene_count"]
df_enrich["-log10(p)"] = -np.log10(df_enrich["p_value"].astype(float))  # 转换p值用于Y轴

fig, ax = plt.subplots(figsize=(8, 6))
scatter = ax.scatter(
    x=df_enrich["odds_ratio"].astype(float),  # X轴:富集倍数
    y=df_enrich["-log10(p)"],                  # Y轴:统计显著性
    s=df_enrich["gene_count"].astype(float) * 5,  # 气泡大小:基因数量
    c=df_enrich["-log10(p)"],                  # 气泡颜色:显著性程度
    cmap="Reds",
    alpha=0.7,
    edgecolors="black",
    linewidths=0.5
)

# 添加通路标签
for _, row in df_enrich.iterrows():
    ax.annotate(
        row["Pathway"],
        xy=(float(row["odds_ratio"]), row["-log10(p)"]),
        xytext=(5, 5), textcoords="offset points",
        fontsize=9
    )

plt.colorbar(scatter, label="-log10(p-value)")
ax.set_xlabel("Odds Ratio (Enrichment Fold)")
ax.set_ylabel("-log10(p-value)")
ax.set_title("Pathway Enrichment Bubble Plot")
ax.axhline(-np.log10(0.05), color="red", linestyle="--", label="p=0.05")
ax.legend()
plt.tight_layout()
plt.savefig("enrichment_bubble.png", dpi=150)
print("气泡图已保存")

# ========== 3. 多组学相关性矩阵图 ==========
# 展示不同组学层次之间的相关性
omics_names = ["mRNA", "miRNA", "Protein", "Metabolite"]
# 模拟各组学之间的相关系数
corr_matrix = np.array([
    [1.00, 0.65, 0.72, 0.45],
    [0.65, 1.00, 0.38, 0.52],
    [0.72, 0.38, 1.00, 0.61],
    [0.45, 0.52, 0.61, 1.00]
])

fig, ax = plt.subplots(figsize=(6, 5))
mask = np.triu(np.ones_like(corr_matrix, dtype=bool), k=1)  # 遮住上三角(避免重复)
sns.heatmap(
    corr_matrix,
    annot=True,          # 在格子中显示数值
    fmt=".2f",           # 保留2位小数
    cmap="coolwarm",     # 冷暖色:正相关=红,负相关=蓝
    vmin=-1, vmax=1,     # 相关系数范围固定
    xticklabels=omics_names,
    yticklabels=omics_names,
    ax=ax
)
ax.set_title("Cross-omics Correlation Matrix")
plt.tight_layout()
plt.savefig("cross_omics_corr.png", dpi=150)
print("相关矩阵图已保存")

面试常问点

  1. Q: 为什么不推荐用彩虹色(rainbow colormap)? A: 彩虹色在亮度上不是单调的,会产生虚假的视觉对比;色盲用户无法区分;推荐viridis/RdBu等感知均匀的色板。

  2. Q: 热图行列聚类的距离度量怎么选? A: 基因表达通常用1-相关系数(correlation distance);欧氏距离适合量级有意义的场景;ward.D2方法常用。

  3. Q: 如何在一张图展示4种组学数据? A: ComplexHeatmap可以画多个并列热图,共享行(样本)聚类;或用UpSet图展示特征在各组学的重叠情况。


速查表

工具语言最强功能
ComplexHeatmapR多注释层热图
ggplot2R高度定制化图表
seabornPython统计可视化
plotlyPython/R交互式图表
CytoscapeGUI网络可视化
UMAPPython降维散点图