
最近在分析一个实验室做的转录组测序数据,直接从上游测序公司定量好的count矩阵开始下游的分析。首先,这个上游数据定量是有问题的,其与参考基因组的比对率只有18%左右。具体是哪个环节出了问题,这里不做考究,直接看看直接差异基因分析,能得到什么样的结果。
第一次分析
rm(list = ls())
library(dplyr)
library(openxlsx)
library(DESeq2)
#大鼠
exp <- read.xlsx("../data/Rattus norvegicus/Expression_with_annotation.xlsx")
colnames(exp)
select_name <- c("Name","cg_1:read.count","cg_2:read.count","cg_3:read.count",
"cg_Icariin_1:read.count","cg_Icariin_2:read.count","cg_Icariin_3:read.count")
exp <- exp[,select_name]
dim(exp) #22016 7
exp[1:2,]
table(duplicated(exp$Name))
#数据清洗
# ---------- 1. 去除重复基因(保留总表达量最高的记录) ----------
exp <- exp %>%
mutate(TotalCount = rowSums(across(-Name))) %>%
arrange(desc(TotalCount)) %>%
distinct(Name, .keep_all = TRUE) %>%
select(-TotalCount)
exp <- as.data.frame(exp)
rownames(exp) <- exp$Name
exp <- exp[, -1]
colnames(exp) <- c(
"Control1", "Control2", "Control3",
"Icariin1", "Icariin2", "Icariin3"
)
exp <- as.matrix(exp)
storage.mode(exp) <- "integer"
dim(exp)#21812 6
head(exp)
sum(duplicated(rownames(exp)))
#过滤
keep_feature <- rowSums (exp > 1) > 1
table(keep_feature)
exp_clean <- exp[keep_feature, ]
dim(exp_clean)#7767 6
colnames(exp_clean)
class(exp_clean)
exp_clean <- as.data.frame(exp_clean)
#分组信息
library(stringr)
k = str_detect(colnames(exp),"Control")
table(k)
Group = ifelse(k,"Control","Icariin")
Group = factor(Group,levels = c("Control","Icariin"))
Group
# [1] Control Control Control Icariin Icariin Icariin
# Levels: Control Icariin
#差异基因分析
group_list <- Group
exprSet = exp_clean
(colData <- data.frame(row.names=colnames(exprSet),
group_list=group_list) )
exprSet[, 1:ncol(exprSet)] <- lapply(exprSet[, 1:ncol(exprSet)], as.integer)
class(exprSet)
dds <- DESeqDataSetFromMatrix(countData = exprSet,
colData = colData,
design = ~ group_list)
dds <- DESeq(dds)
res <- results(dds,
contrast=c("group_list",
levels(group_list)[2],
levels(group_list)[1]))
resOrdered <- res[order(res$padj),]
head(resOrdered)
DEG =as.data.frame(resOrdered)
dim(DEG)#7767 6
deg = na.omit(DEG)
#差异基因分析
logFC_t = 0.585
p_t = 0.05
k1 = (deg$pvalue < p_t)&(deg$log2FoldChange < -logFC_t)
k2 = (deg$pvalue < p_t)&(deg$log2FoldChange > logFC_t)
deg = mutate(deg,change = ifelse(k1,"Down",ifelse(k2,"Up","Not")))
table(deg$change)
# Down Not Up
# 13 2469 15 做到这就能发现问题了,我的dim(exp_clean)是7767 6,即7767个基因,为什么最后的deg$change只显示13 + 2469 +15 = 2497个基因呢?也就是说,有5,270个基因在DESeq2分析后被排除,约占全部基因的67.9%。而这套差异分析的代码我用了很多年了,一直没有出现过这样的情况。
细究之下发现,
> dim(DEG)#7767 6
[1] 7767 6
> deg = na.omit(DEG)
> dim(deg)
[1] 2497 6
> # 1. 原始表达矩阵基因数
> nrow(exp_clean)
[1] 7767
> # 2. DESeq2完整结果基因数
> nrow(DEG)
[1] 7767
> # 3. na.omit后剩余基因数
> nrow(na.omit(DEG))
[1] 2497
> # 4. 分别检查各列NA数量
> colSums(is.na(DEG))
baseMean log2FoldChange lfcSE stat pvalue padj
0 0 0 0 0 5270
> # 5. 检查P值和校正P值
> table(is.na(DEG$pvalue))
FALSE
7767
> table(is.na(DEG$padj))
FALSE TRUE
2497 5270 即正常情况下,DEG 应该仍有7,767行,每个基因对应一条统计结果,但是,DESeq2的结果中可能存在NA,特别是 padj 列。DESeq2默认采用独立过滤(Independent filtering)机制。对于平均表达量较低、统计检验效能不足的基因,DESeq2可能将其校正后的P值(padj)设置为NA,但这些基因的原始P值(pvalue)仍可能是有效的。
而我设置的的差异表达基因筛选标准是,使用的是原始P值,而不是padj。就可能导致实际上满足设置的差异筛选标准,却被提前删除了。这就可能造成差异表达基因数量被低估。
#使用原始P值筛选
logFC_t = 0.585
p_t = 0.05
k1 = (deg$pvalue < p_t) &
(deg$log2FoldChange < -logFC_t)
k2 = (deg$pvalue < p_t) &
(deg$log2FoldChange > logFC_t)如我第二次分析,不再执行deg = na.omit(DEG),而是直接执行deg <- DEG,后续分析步骤不变,就会出现差异基因数量显著增多。
> deg <- DEG
> dim(deg)
[1] 7767 6
...
logFC_t = 0.585
p_t = 0.05
k1 = (deg$pvalue < p_t)&(deg$log2FoldChange < -logFC_t)
k2 = (deg$pvalue < p_t)&(deg$log2FoldChange > logFC_t)
deg = mutate(deg,change = ifelse(k1,"Down",ifelse(k2,"Up","Not")))
table(deg$change)
# Down Not Up
# 77 7615 75 当然,原来的分析代码并不能说错的,只是又额外过滤了一遍。之前没有注意到这个问题,这次分析了一个有问题的矩阵,显著放大了这个问题,才被我注意到。这里写篇帖子记录下。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。