R语言可视化(R Visualization for Bioinformatics)¶
一句话说明¶
R是生信领域最常用的统计与可视化语言,ggplot2生态是制作发表级图表的标准工具。掌握R可视化是生信分析工程师从"出结果"到"出图发表"的核心能力。
2. 核心知识点¶
2.1 ggplot2基础——图形语法(Grammar of Graphics)¶
ggplot2基于Leland Wilkinson的图形语法理论,将图表拆分为独立组件,通过+号逐层叠加:
| 组件 | 英文 | 函数 | 说明 |
|---|---|---|---|
| 数据 | Data | ggplot(data) |
输入的data.frame |
| 映射 | Aesthetics | aes(x, y, color, fill, size) |
变量→视觉属性 |
| 几何对象 | Geometry | geom_*() |
图表类型(点/线/柱等) |
| 统计变换 | Statistics | stat_*() |
均值、计数、回归线 |
| 标度 | Scales | scale_*() |
颜色、坐标轴刻度 |
| 分面 | Facets | facet_wrap() / facet_grid() |
按变量拆分子图 |
| 坐标系 | Coordinate | coord_*() |
笛卡尔/极坐标 |
| 主题 | Theme | theme_*() |
字体、背景、网格线 |
核心公式:
ggplot(data, aes(x, y)) + geom_*() + scale_*() + theme_*()
2.2 常用geom几何对象¶
| geom | 图表类型 | 典型用途 |
|---|---|---|
geom_bar() / geom_col() |
柱状图 | 物种丰度、功能注释计数 |
geom_boxplot() |
箱线图 | Alpha多样性比较 |
geom_violin() |
小提琴图 | 数据分布展示 |
geom_point() |
散点图 | PCoA/PCA/NMDS |
geom_tile() |
热图块 | 简单热图 |
geom_line() |
折线图 | 稀释曲线 |
geom_errorbar() |
误差线 | 均值+标准差 |
geom_text() / geom_label() |
文字标注 | 图上标数值 |
geom_density() |
密度图 | reads长度分布 |
geom_hline() / geom_vline() |
参考线 | 阈值线(如p=0.05) |
2.3 生信常用图表¶
| 图表类型 | ggplot2实现 | 用途 | 典型包 |
|---|---|---|---|
| 物种丰度堆叠柱状图 | geom_bar(stat="identity", position="stack") |
展示各样本物种组成 | ggplot2 |
| Alpha多样性箱线图 | geom_boxplot() + stat_compare_means() |
组间多样性差异比较 | ggplot2 + ggpubr |
| PCoA散点图 | geom_point() + stat_ellipse() |
Beta多样性可视化 | ggplot2 + vegan |
| 热图 | 独立函数(非ggplot2) | 物种/基因表达聚类 | pheatmap / ComplexHeatmap |
| 韦恩图 | 独立函数 | 组间共有/特有物种 | VennDiagram / UpSetR |
| LEfSe柱状图 | geom_bar(stat="identity") + coord_flip() |
差异物种展示 | ggplot2 |
| 弦图/网络图 | chordDiagram() |
物种-功能关联 | circlize |
| 火山图 | geom_point() 着色 |
差异分析结果 | ggplot2 / EnhancedVolcano |
| 稀释曲线 | geom_line() |
测序深度是否足够 | ggplot2 + vegan |
| 桑基图 | 独立函数 | 物种分类层级 | ggalluvial / networkD3 |
2.4 差异分析R包¶
DESeq2(最常用)¶
| 要素 | 说明 |
|---|---|
| 输入 | 原始count矩阵(raw counts,未归一化) |
| 归一化 | 中位数比率法(Median of Ratios) |
| 统计模型 | 负二项分布(Negative Binomial) |
| 适用场景 | 样本量较小(<20)、RNA-seq、宏基因组差异物种 |
| 核心函数 | DESeqDataSetFromMatrix() → DESeq() → results() |
| 结果 | log2FoldChange, padj(BH校正后的p值) |
edgeR¶
| 要素 | 说明 |
|---|---|
| 输入 | 原始count矩阵 |
| 归一化 | TMM(Trimmed Mean of M-values) |
| 统计模型 | 负二项分布 |
| 适用场景 | 样本量较大、比DESeq2更灵活 |
| 核心函数 | DGEList() → calcNormFactors() → estimateDisp() → exactTest() |
limma-voom¶
| 要素 | 说明 |
|---|---|
| 输入 | count矩阵(经voom转换) |
| 统计模型 | 线性模型 + 经验贝叶斯 |
| 适用场景 | 样本量大(>30)、复杂实验设计 |
ALDEx2(组学专用)¶
| 要素 | 说明 |
|---|---|
| 输入 | count矩阵 |
| 特点 | 基于CLR变换(Centered Log-Ratio),专为组成型数据设计 |
| 适用场景 | 微生物组数据(丰度是相对比例,天然组成型) |
DESeq2 vs edgeR 对比:
| 对比项 | DESeq2 | edgeR |
|---|---|---|
| 归一化 | Median of Ratios | TMM |
| 小样本 | 更稳健 | 需注意 |
| 速度 | 稍慢 | 更快 |
| 使用难度 | 更简洁 | 需更多手动步骤 |
| 引用量 | 更高 | 略低 |
| 推荐场景 | 初学者首选 | 高级用户/复杂设计 |
3. 实战代码¶
3.1 物种丰度Top10堆叠柱状图¶
# ============================================================
# 物种丰度 Top10 堆叠柱状图
# Species Abundance Top10 Stacked Bar Plot
# ============================================================
# --- 加载包 ---
library(ggplot2) # 绘图核心包
library(dplyr) # 数据处理
library(tidyr) # 数据整理(长宽转换)
library(RColorBrewer) # 配色方案
# --- 读取数据 ---
# 假设文件是 Kraken2/Bracken 输出的物种丰度表
# 行 = 物种,列 = 样本,值 = 相对丰度(百分比或比例)
abundance <- read.csv("species_abundance.csv", row.names = 1, check.names = FALSE)
# check.names=FALSE 防止R自动修改列名中的特殊字符
# --- 查看数据结构 ---
head(abundance)
# 期望格式:
# Sample1 Sample2 Sample3
# E.coli 0.42 0.57 0.35
# B.fragilis 0.15 0.08 0.20
# ...
# --- 筛选Top10物种 ---
# 按所有样本的平均丰度排序,取前10
top10_species <- abundance %>%
mutate(species = rownames(abundance)) %>% # 行名转列
mutate(mean_abundance = rowMeans(select(., -species))) %>% # 计算平均丰度
arrange(desc(mean_abundance)) %>% # 降序排列
head(10) %>% # 取前10
pull(species) # 提取物种名
# --- 将非Top10合并为"Others" ---
abundance_top10 <- abundance
abundance_top10$species <- rownames(abundance_top10)
abundance_top10 <- abundance_top10 %>%
mutate(species = ifelse(species %in% top10_species, species, "Others")) %>%
group_by(species) %>%
summarise(across(everything(), sum)) %>% # 合并"Others"行
ungroup()
# --- 转为长格式(ggplot2 要求) ---
abundance_long <- abundance_top10 %>%
pivot_longer(cols = -species, names_to = "sample", values_to = "abundance")
# --- 设置物种顺序(Top10 + Others) ---
species_order <- c(top10_species, "Others")
abundance_long$species <- factor(abundance_long$species, levels = rev(species_order))
# rev()反转顺序,让最丰富的物种在柱子顶部
# --- 配色 ---
n_colors <- length(species_order)
my_colors <- c(brewer.pal(min(n_colors - 1, 10), "Set3"), "grey70")
# "Others"用灰色
# --- 画图 ---
p <- ggplot(abundance_long, aes(x = sample, y = abundance, fill = species)) +
geom_bar(stat = "identity", position = "stack", width = 0.7) + # 堆叠柱状图
scale_fill_manual(values = my_colors) + # 自定义颜色
labs(
title = "Species Abundance (Top 10)",
x = "Sample",
y = "Relative Abundance",
fill = "Species"
) +
theme_classic() + # 简洁主题
theme(
axis.text.x = element_text(angle = 45, hjust = 1, size = 10), # X轴标签倾斜45度
legend.position = "right",
plot.title = element_text(hjust = 0.5, face = "bold") # 标题居中加粗
)
# --- 保存图片 ---
ggsave("species_top10_barplot.pdf", p, width = 10, height = 6, dpi = 300)
ggsave("species_top10_barplot.png", p, width = 10, height = 6, dpi = 300)
cat("图片已保存: species_top10_barplot.pdf / .png\n")
3.2 Alpha多样性箱线图 + Wilcoxon检验¶
# ============================================================
# Alpha多样性(Shannon)箱线图 + 统计检验
# Alpha Diversity (Shannon) Boxplot with Wilcoxon Test
# ============================================================
library(ggplot2)
library(ggpubr) # stat_compare_means() 统计检验标注
library(vegan) # diversity() 计算多样性指数
# --- 读取数据 ---
# OTU/ASV 丰度表:行=物种,列=样本
otu_table <- read.csv("otu_table.csv", row.names = 1, check.names = FALSE)
# 分组信息:sample_id + group
metadata <- read.csv("metadata.csv")
# 期望格式:
# sample_id group
# Sample1 Disease
# Sample2 Healthy
# --- 计算Shannon多样性指数 ---
# vegan::diversity() 要求输入矩阵:行=样本,列=物种(注意需要转置)
shannon <- diversity(t(otu_table), index = "shannon")
# t() 转置矩阵,因为我们的数据是物种×样本格式
# --- 合并分组信息 ---
div_df <- data.frame(
sample_id = names(shannon),
shannon = shannon,
stringsAsFactors = FALSE
)
div_df <- merge(div_df, metadata, by = "sample_id")
# --- 画箱线图 ---
p <- ggplot(div_df, aes(x = group, y = shannon, fill = group)) +
geom_boxplot(
alpha = 0.7, # 透明度
outlier.shape = 16, # 异常值形状
width = 0.5
) +
geom_jitter( # 叠加散点,显示每个样本
width = 0.15,
size = 2,
alpha = 0.6
) +
stat_compare_means( # Wilcoxon秩和检验(非参数检验)
method = "wilcox.test",
label = "p.signif", # 显示显著性星号(* ** *** ns)
label.x = 1.5,
label.y = max(div_df$shannon) * 1.1
) +
scale_fill_manual(values = c("Disease" = "#E74C3C", "Healthy" = "#3498DB")) +
labs(
title = "Alpha Diversity (Shannon Index)",
x = "Group",
y = "Shannon Index",
fill = "Group"
) +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "none" # 箱线图已有颜色区分,不需要图例
)
# --- 保存 ---
ggsave("alpha_shannon_boxplot.pdf", p, width = 6, height = 5, dpi = 300)
cat("图片已保存: alpha_shannon_boxplot.pdf\n")
# --- 输出统计结果 ---
wilcox_result <- wilcox.test(shannon ~ group, data = div_df)
cat("Wilcoxon test p-value:", wilcox_result$p.value, "\n")
3.3 Bray-Curtis PCoA散点图¶
# ============================================================
# PCoA散点图(Bray-Curtis距离)
# PCoA Plot Based on Bray-Curtis Dissimilarity
# ============================================================
library(ggplot2)
library(vegan) # vegdist() 距离矩阵 + cmdscale/ape::pcoa
library(ape) # pcoa() 主坐标分析
# --- 读取数据 ---
otu_table <- read.csv("otu_table.csv", row.names = 1, check.names = FALSE)
metadata <- read.csv("metadata.csv")
# --- 计算 Bray-Curtis 距离矩阵 ---
# vegdist() 输入:行=样本,列=物种
bray_dist <- vegdist(t(otu_table), method = "bray")
# 返回一个距离矩阵对象(dist class)
# --- PCoA 分析 ---
pcoa_result <- pcoa(bray_dist)
# --- 提取坐标和解释度 ---
pcoa_coords <- as.data.frame(pcoa_result$vectors[, 1:2]) # 取前2个轴
colnames(pcoa_coords) <- c("PCoA1", "PCoA2")
pcoa_coords$sample_id <- rownames(pcoa_coords)
# 计算各轴解释变异的百分比
# 用 Relative_eig 更准确(已处理负特征值情况)
var_explained <- round(pcoa_result$values$Relative_eig * 100, 1)
# var_explained[1] 是第一轴解释百分比
# var_explained[2] 是第二轴解释百分比
# --- 合并分组信息 ---
pcoa_df <- merge(pcoa_coords, metadata, by = "sample_id")
# --- 画PCoA图 ---
p <- ggplot(pcoa_df, aes(x = PCoA1, y = PCoA2, color = group)) +
geom_point(size = 4, alpha = 0.8) + # 散点
stat_ellipse( # 95%置信椭圆
level = 0.95,
type = "t", # t分布椭圆
linetype = "dashed",
linewidth = 0.8
) +
scale_color_manual(values = c("Disease" = "#E74C3C", "Healthy" = "#3498DB")) +
labs(
title = "PCoA (Bray-Curtis Dissimilarity)",
x = paste0("PCoA1 (", var_explained[1], "%)"), # 轴标签加解释度
y = paste0("PCoA2 (", var_explained[2], "%)"),
color = "Group"
) +
theme_classic() +
theme(
plot.title = element_text(hjust = 0.5, face = "bold"),
legend.position = "right"
)
# --- PERMANOVA 统计检验(与PCoA配套) ---
# 检验组间差异是否显著
permanova <- adonis2(bray_dist ~ group, data = pcoa_df, permutations = 999)
cat("PERMANOVA p-value:", permanova$`Pr(>F)`[1], "\n")
cat("PERMANOVA R2:", permanova$R2[1], "\n")
# R2 表示分组因素解释了多少变异
# 在图上添加PERMANOVA结果
p <- p + annotate(
"text",
x = min(pcoa_df$PCoA1),
y = max(pcoa_df$PCoA2),
label = paste0("PERMANOVA\nR2=", round(permanova$R2[1], 3),
"\np=", permanova$`Pr(>F)`[1]),
hjust = 0, vjust = 1, size = 3.5
)
# --- 保存 ---
ggsave("pcoa_braycurtis.pdf", p, width = 8, height = 6, dpi = 300)
cat("图片已保存: pcoa_braycurtis.pdf\n")
3.4 热图(pheatmap)¶
# ============================================================
# 物种丰度热图
# Species Abundance Heatmap with pheatmap
# ============================================================
library(pheatmap) # 热图专用包(自带聚类)
library(dplyr)
# --- 读取数据 ---
abundance <- read.csv("species_abundance.csv", row.names = 1, check.names = FALSE)
metadata <- read.csv("metadata.csv")
# --- 筛选 Top20 物种 ---
top20 <- names(sort(rowMeans(abundance), decreasing = TRUE))[1:20]
mat <- as.matrix(abundance[top20, ])
# --- Z-score 标准化(按行,即按物种) ---
# Z-score = (x - mean) / sd
# 目的:消除不同物种之间丰度量级差异,便于比较模式
mat_scaled <- t(scale(t(mat)))
# 内层 t(mat) 转置 → scale() 按列标准化 → 外层 t() 转回来
# 效果:每个物种(行)均值=0,标准差=1
# --- 列注释(样本分组) ---
annotation_col <- data.frame(
Group = metadata$group,
row.names = metadata$sample_id
)
# --- 自定义注释颜色 ---
ann_colors <- list(
Group = c("Disease" = "#E74C3C", "Healthy" = "#3498DB")
)
# --- 画热图 ---
pdf("heatmap_top20.pdf", width = 10, height = 8)
pheatmap(
mat_scaled,
color = colorRampPalette(c("#2166AC", "white", "#B2182B"))(100), # 蓝-白-红
clustering_method = "ward.D2", # 聚类方法:Ward最小方差法
clustering_distance_rows = "euclidean", # 行聚类距离
clustering_distance_cols = "euclidean", # 列聚类距离
annotation_col = annotation_col, # 列注释(分组信息)
annotation_colors = ann_colors, # 注释颜色
show_colnames = TRUE, # 显示列名(样本名)
show_rownames = TRUE, # 显示行名(物种名)
fontsize_row = 8, # 行标签字号
fontsize_col = 9, # 列标签字号
main = "Top 20 Species Abundance (Z-score)" # 标题
)
dev.off()
cat("图片已保存: heatmap_top20.pdf\n")
热图聚类方法选择:
| 聚类方法 | R参数 | 特点 | 推荐场景 |
|---|---|---|---|
| Ward最小方差 | "ward.D2" |
倾向生成大小均匀的簇 | 最常用,默认推荐 |
| 完全连接 | "complete" |
保守,簇间距离大 | 想找明显分群 |
| 平均连接 | "average" |
折中 | 一般情况 |
| 单连接 | "single" |
倾向链状聚类 | 少用 |
3.5 DESeq2差异分析基本流程¶
# ============================================================
# DESeq2 差异分析基本流程
# DESeq2 Differential Analysis Pipeline
# ============================================================
library(DESeq2) # 差异分析核心包
library(ggplot2)
library(dplyr)
# --- 读取数据 ---
# ⚠️ DESeq2 输入必须是原始 count(整数),不能是 TPM/FPKM/归一化后的值
count_matrix <- read.csv("raw_counts.csv", row.names = 1, check.names = FALSE)
count_matrix <- as.matrix(count_matrix) # 转为矩阵
# 确保是整数
count_matrix <- round(count_matrix) # 如果有小数,四舍五入
# 分组信息
col_data <- read.csv("metadata.csv", row.names = 1)
# 期望格式(行名=样本名,必须与count_matrix列名一致):
# group
# Sample1 Disease
# Sample2 Healthy
# --- 确保样本顺序一致 ---
count_matrix <- count_matrix[, rownames(col_data)]
# --- 创建 DESeq2 数据对象 ---
dds <- DESeqDataSetFromMatrix(
countData = count_matrix, # 原始count矩阵
colData = col_data, # 样本分组信息
design = ~ group # 实验设计公式:按group分组比较
)
# --- 预过滤(去除低表达基因/物种) ---
# 至少在某些样本中有一定表达量,减少多重检验负担
keep <- rowSums(counts(dds)) >= 10
dds <- dds[keep, ]
# --- 运行 DESeq2 ---
dds <- DESeq(dds)
# 内部自动完成:
# 1. 归一化(Median of Ratios)
# 2. 离散度估计(dispersion estimation)
# 3. 负二项分布检验(Wald test)
# --- 提取结果 ---
res <- results(dds, contrast = c("group", "Disease", "Healthy"))
# contrast: c(分组列名, 实验组, 对照组)
# log2FoldChange > 0 表示 Disease 组上调
# log2FoldChange < 0 表示 Disease 组下调
# --- 查看结果摘要 ---
summary(res)
# --- 添加显著性标记 ---
res_df <- as.data.frame(res) %>%
mutate(
gene = rownames(res),
significance = case_when(
padj < 0.05 & log2FoldChange > 1 ~ "Up", # 上调:padj<0.05 且 |log2FC|>1
padj < 0.05 & log2FoldChange < -1 ~ "Down", # 下调
TRUE ~ "NS" # 不显著(Not Significant)
)
)
# --- 火山图(Volcano Plot) ---
p <- ggplot(res_df, aes(x = log2FoldChange, y = -log10(padj), color = significance)) +
geom_point(alpha = 0.6, size = 1.5) +
scale_color_manual(values = c("Up" = "#E74C3C", "Down" = "#3498DB", "NS" = "grey60")) +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "grey40") + # p=0.05线
geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "grey40") + # |log2FC|=1线
labs(
title = "Volcano Plot (DESeq2)",
x = "log2 Fold Change (Disease / Healthy)",
y = "-log10(adjusted p-value)",
color = "Significance"
) +
theme_classic() +
theme(plot.title = element_text(hjust = 0.5, face = "bold"))
# --- 保存火山图 ---
ggsave("volcano_plot.pdf", p, width = 8, height = 6, dpi = 300)
# --- 导出差异结果 ---
write.csv(res_df, "DESeq2_results.csv", row.names = FALSE)
cat("差异分析完成,结果已保存: DESeq2_results.csv + volcano_plot.pdf\n")
# --- 输出显著基因/物种数量 ---
cat("上调:", sum(res_df$significance == "Up"), "\n")
cat("下调:", sum(res_df$significance == "Down"), "\n")
cat("不显著:", sum(res_df$significance == "NS"), "\n")
4. 面试常问点¶
★ ggplot2的图形语法是什么?¶
参考答案:ggplot2基于图形语法(Grammar of Graphics)理论,把一张图拆分成数据(data)、映射(aesthetics)、几何对象(geom)、标度(scales)、分面(facets)、主题(theme)等独立组件,通过
+号逐层叠加。好处是灵活、可组合,比如同一个数据可以快速切换柱状图和箱线图,只要换一个geom_*()就行。💡 加分回答:在百迈客实习时,我用ggplot2画过物种丰度堆叠柱状图和Alpha多样性箱线图,图形语法的分层设计让我可以快速调配色、分面、加统计标注。
★ 你常用R画什么图?¶
参考答案:在实习和个人项目中,我最常画的是: 1. 物种丰度堆叠柱状图 —— 展示各样本的物种组成 2. Alpha多样性箱线图 —— Shannon/Chao1 + Wilcoxon检验比较组间差异 3. PCoA散点图 —— 基于Bray-Curtis距离展示Beta多样性 4. 热图 —— 用pheatmap做Top物种的聚类热图 5. LEfSe柱状图 —— 展示差异物种的LDA值
这些图在宏基因组和16S分析中几乎每个项目都会用到。
★ DESeq2和edgeR的区别?¶
参考答案:两者都基于负二项分布检验count数据的差异,核心区别是: 1. 归一化方法不同:DESeq2用中位数比率法(Median of Ratios),edgeR用TMM 2. 小样本表现:DESeq2对小样本(<20)更稳健,因为它的离散度估计(shrinkage)更保守 3. 使用复杂度:DESeq2一步到位(
DESeq()封装了所有步骤),edgeR需要手动分步执行 4. 选择建议:初学者或小样本推荐DESeq2;复杂实验设计或大样本可以用edgeR⚠️ 关键点:两者的输入都必须是原始count(raw counts),不能用归一化后的值(如TPM、FPKM)。
★ 热图的聚类方法有哪些?¶
参考答案:pheatmap中常用的聚类方法有: - Ward最小方差法(ward.D2) —— 最常用,倾向生成大小均匀的簇 - 完全连接法(complete) —— 用簇间最大距离,比较保守 - 平均连接法(average/UPGMA) —— 用簇间平均距离,比较折中
距离度量通常用欧氏距离(euclidean)或相关性距离(1-cor)。
⚠️ 关键点:做热图之前一般要对数据做Z-score标准化(按行/按基因),否则高丰度物种会主导颜色,看不到低丰度物种的变化模式。
★ PCoA图怎么画?用什么包?¶
参考答案:PCoA的R语言流程是: 1. 用
vegan::vegdist()计算Bray-Curtis距离矩阵 2. 用ape::pcoa()做主坐标分析,得到坐标和特征值 3. 用ggplot2::geom_point()画散点图,stat_ellipse()加置信椭圆 4. 轴标签要标注解释变异百分比(如"PCoA1 (35.2%)") 5. 配套做PERMANOVA(vegan::adonis2())检验组间差异是否显著💡 加分回答:在我的肠道宏基因组项目中,PCoA图显示Disease组和Healthy组有明显分离趋势,Bray-Curtis距离为0.20,PERMANOVA检验显著,说明两组菌群组成存在差异。
5. 易错/易混淆点¶
⚠️ ggplot2的+和%>%不要混用¶
# 正确:ggplot2 用 + 连接图层
ggplot(data, aes(x, y)) +
geom_point() +
theme_classic()
# 错误:不能用管道符连接 ggplot 图层
ggplot(data, aes(x, y)) %>% # 这里会报错!
geom_point()
# 注意:数据处理可以用 %>%,但到 ggplot() 之后就要换成 +
data %>%
filter(group == "Disease") %>%
ggplot(aes(x, y)) + # 从这里开始用 +
geom_point()
⚠️ aes()里面和外面设置颜色的区别¶
# aes() 里面:颜色映射到变量(自动生成图例)
geom_point(aes(color = group)) # 按group分组着色
# aes() 外面:所有点设为同一颜色(不生成图例)
geom_point(color = "red") # 所有点都是红色
# 常见错误:在 aes() 里写固定颜色
geom_point(aes(color = "red")) # 错!R会把"red"当作一个常量变量
⚠️ 热图数据需要标准化(Z-score)¶
# 错误:直接用原始丰度画热图
pheatmap(raw_abundance) # 高丰度物种主导颜色,信息丢失
# 正确:先做 Z-score 标准化
mat_scaled <- t(scale(t(raw_abundance))) # 按行(物种)标准化
pheatmap(mat_scaled) # 展示相对变化模式
⚠️ DESeq2输入必须是raw count¶
# 错误:输入 TPM/FPKM/归一化后的值
dds <- DESeqDataSetFromMatrix(countData = tpm_matrix, ...) # 结果不可靠!
# 正确:输入原始 count(整数)
dds <- DESeqDataSetFromMatrix(countData = raw_count_matrix, ...)
# 如果数据有小数(如Bracken输出),需要四舍五入
count_matrix <- round(count_matrix)
⚠️ padj vs pvalue¶
# 差异分析结果中有两个p值:
# pvalue - 未校正的原始p值
# padj - 经过多重检验校正(BH/FDR)后的p值
# 正确:用 padj 筛选差异基因
sig_genes <- res_df %>% filter(padj < 0.05)
# 错误:用 pvalue 筛选(假阳性太高)
sig_genes <- res_df %>% filter(pvalue < 0.05) # 不推荐!
⚠️ pheatmap vs ComplexHeatmap¶
| 特性 | pheatmap | ComplexHeatmap |
|---|---|---|
| 上手难度 | 简单,一个函数搞定 | 复杂,灵活度高 |
| 多热图拼接 | 不支持 | 支持 |
| 注释条 | 简单注释 | 复杂多层注释 |
| 推荐场景 | 日常使用、快速出图 | 发表级复杂热图 |
| 面试推荐 | 先说pheatmap | 补充提ComplexHeatmap |
6. 快速复习卡片¶
| 问题 | 一句话答案 |
|---|---|
| ggplot2核心公式 | ggplot(data, aes()) + geom_*() + scale_*() + theme_*() |
| 图形语法几大组件 | 数据、映射、几何对象、标度、分面、坐标系、主题 |
| 常用热图包 | pheatmap(简单)、ComplexHeatmap(复杂) |
| DESeq2输入 | 原始count(整数),不能用TPM/FPKM |
| DESeq2归一化 | Median of Ratios(中位数比率法) |
| edgeR归一化 | TMM(Trimmed Mean of M-values) |
| PCoA流程 | vegdist() → pcoa() → ggplot + geom_point + stat_ellipse |
| PERMANOVA函数 | vegan::adonis2() |
| Z-score标准化 | t(scale(t(matrix))) 按行标准化 |
| padj vs pvalue | 用padj(BH校正后),不用原始pvalue |