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("相关矩阵图已保存")
面试常问点¶
Q: 为什么不推荐用彩虹色(rainbow colormap)? A: 彩虹色在亮度上不是单调的,会产生虚假的视觉对比;色盲用户无法区分;推荐viridis/RdBu等感知均匀的色板。
Q: 热图行列聚类的距离度量怎么选? A: 基因表达通常用1-相关系数(correlation distance);欧氏距离适合量级有意义的场景;ward.D2方法常用。
Q: 如何在一张图展示4种组学数据? A: ComplexHeatmap可以画多个并列热图,共享行(样本)聚类;或用UpSet图展示特征在各组学的重叠情况。
速查表¶
| 工具 | 语言 | 最强功能 |
|---|---|---|
| ComplexHeatmap | R | 多注释层热图 |
| ggplot2 | R | 高度定制化图表 |
| seaborn | Python | 统计可视化 |
| plotly | Python/R | 交互式图表 |
| Cytoscape | GUI | 网络可视化 |
| UMAP | Python | 降维散点图 |