經典的轉錄組差異分析通常會使用到三個工具limma/voom
, edgeR
和DESeq2
, 今天我們同樣使用一個小規模的轉錄組測序數據來演示edgeR
的簡單流程。
由于,edgeR
和DESeq2
都是使用基于負二項分布的廣義線性回歸模型(GLM)來對RNA-seq數據進行擬合和差異分析,所以我們都用同一個數據來分析。
文中使用的數據來自Standford 大學的一個擬南芥的small RNA-seq數據(https://bios221.stanford.edu/data/mobData.RData)
該數據包含6個樣本:SL236,SL260,SL237,SL238,SL239,SL240, 并分成了三組,分別是:
MM="triple mutatnt shoot grafted onto triple mutant root"
WM="wild-type shoot grafted onto triple mutant root"
WW="wild-type shoot grafted onto wild-type root"
簡而言之,
WW
組可以認為是實驗的對照組,而MM
和WM
則是兩個處理組。
P.S. 本文的分析是基于有生物學重復的單因子差異分析,關于無生物學重復或者多因子的情況,以后有機會再做展開。
對于edgeR
的分析流程而言,我們需要輸入的數據包括:
- 表達矩陣(
counts
) - 分組信息(
group
) - 擬合信息(
design
):指明如何根據樣本的分組進行建模
下面就以mobData
中的數據為例簡單介紹edgeR
的分析流程
載入數據及生成DGEList
由于mobData
中的行名沒有提供基因的ID,我們也不是為了探究生物學問題,就以mobData
的行數作為其ID
library(edgeR)
load("data/mobData.RData")
head(mobData)
## SL236 SL260 SL237 SL238 SL239 SL240
## [1,] 21 52 4 4 86 68
## [2,] 18 21 1 5 1 1
## [3,] 1 2 2 3 0 0
## [4,] 68 87 270 184 396 368
## [5,] 68 87 270 183 396 368
## [6,] 1 0 6 10 6 12
row.names(mobData) <- as.character(c(1:dim(mobData)[1]))
# MM="triple mutatnt shoot grafted onto triple mutant root"
# WM="wild-type shoot grafted onto triple mutant root"
# WW="wild-type shoot grafted onto wild-type root"
mobGroups <- c("MM", "MM", "WM", "WM", "WW", "WW")
degs <- DGEList(counts = mobData, group = mobGroups);degs
## An object of class "DGEList"
## $counts
## SL236 SL260 SL237 SL238 SL239 SL240
## 1 21 52 4 4 86 68
## 2 18 21 1 5 1 1
## 3 1 2 2 3 0 0
## 4 68 87 270 184 396 368
## 5 68 87 270 183 396 368
## 2995 more rows ...
##
## $samples
## group lib.size norm.factors
## SL236 MM 152461 1
## SL260 MM 309995 1
## SL237 WM 216924 1
## SL238 WM 208841 1
## SL239 WW 258404 1
## SL240 WW 276434 1
edgeR
將數據存儲在列表形式的DGEList
對象中,需要指定的參數包括counts
和group
. DGEList
將表達矩陣存儲在$counts
中,將樣本的信息,例如分組情況和文庫大小等存儲在$samples
中。
預處理
在進行差異分析之前,需要對樣本數據的表達矩陣進行預處理,包括:
- 去除低表達量基因
- 探索樣本分組信息 -- 有助于挖掘潛在的差異樣本
這里我們根據CPM normalization后的基因表達量作為過濾低表達基因的指標
# cpm normalization
countsPerMillion <- cpm(degs)
countCheck <- countsPerMillion > 1
keep <- which(rowSums(countCheck) >= 2)
degs.keep <- degs[keep,]
dim(degs.keep)
## [1] 2861 6
edgeR
默認使用 trimmed mean of M-values (TMM) 計算文庫的scale factor進行normalization,以最大程度地縮小樣本間基因表達量的log-fold change。這是因為TMM 法認為樣本間大部分的基因都沒有發生差異表達,而那些真正差異表達的基因并不會受到normalization的嚴重影響。如此一來,便將那些由于測序引起的差異表達基因的表達量給校正了,消除了一部分的假陽性。
degs.norm <- calcNormFactors(degs.keep, method = 'TMM')
plotMDS(degs.norm, col=as.numeric(degs.norm$samples$group))
legend("bottomleft",as.character(unique(degs.norm$samples$group)), col=1:3, pch=20)
這里使用plotMDS
查看樣本的分組情況(通過logFC),各組都分得很開。plotMDS
在多因子的情況下可以更好地觀察各個樣本組是否有良好的分組。
關于Normalization
在差異分析中,我們常常更關注的是相對表達量的變化,例如處理組的A基因表達量相對于對照組的而言是上調還是下調了。而基因表達量的定量準確性則在差異分析中不太重要,因此,在進行差異分析時,像RPKM/FPKM這種對轉錄本長度進行normalization方法是并不常用,也是沒有必要的。
在常規的RNA-seq中,影響基因表達量更大的技術因素往往是測序深度以及有效文庫大小(effective libraries size)。這也是一般的差異分析軟件會進行normalize的部分。
差異分析
首先,我們構建出design
矩陣,指明差異分析所要比較的關系
designMat <- model.matrix(~0+mobGroups);designMat
## mobGroupsMM mobGroupsWM mobGroupsWW
## 1 1 0 0
## 2 1 0 0
## 3 0 1 0
## 4 0 1 0
## 5 0 0 1
## 6 0 0 1
## attr(,"assign")
## [1] 1 1 1
## attr(,"contrasts")
## attr(,"contrasts")$mobGroups
## [1] "contr.treatment"
然后,進行dispersion的估計
degs.norm <- estimateGLMCommonDisp(degs.norm,design=designMat)
degs.norm <- estimateGLMTrendedDisp(degs.norm, design=designMat)
degs.norm <- estimateGLMTagwiseDisp(degs.norm, design=designMat)
plotBCV(degs.norm)
plotBCV
反映不同表達量的基因與模型擬合的情況,如果模型擬合得好則"Tagwise"點的分布會擬合到“Trend”這條曲線上,如上圖所展示的情況。但也可以看到低表達量的基因有點離散。
關于dispersion estimation
一般而言,樣本間的變異系數(coefficient of variance,CV)是由兩部分組成的,一是技術差異(Technical CV),另一個是生物學差異(Biological coefficient of variance,BCV)。前者是會隨著測序通量的提升而消失的,而后者則是樣本間真實存在的差異。所以,對于一個基因g而言,它的BCV在樣本間足夠大的話,就可以認為基因g是一個差異表達基因。而
edgeR
正是通過估計dispersion來估計BCV(其中的數理不在此展開),進而擬合出線性回歸模型的參數。
estimateGLMCommonDisp(x,design)
:為所有基因都計算同樣的dispersion
estimateGLMTrendedDisp(x,design)
:根據不同基因的均值--方差之間的關系來計算dispersion,并擬合一個trended model
estimateGLMTagwiseDisp(x,design)
:計算每個基因的dispersion,并利用經驗性貝葉斯方法(empirical bayes)壓縮至Trend Didspersion。個人認為這一項相當于GLM中每個基因的beta值
最后,根據design
進行擬合,并利用likelihood ratio test(LRT)進行統計檢驗
fit <- glmFit(degs.norm, designMat)
# LRT=likelihood ratio test
# group1-group2
lrt.1vs2 <- glmLRT(fit, contrast = c(1,-1,0))
# group1-group3
lrt.1vs3 <- glmLRT(fit, contrast = c(1,0,-1))
# group2-group3
lrt.2vs3 <- glmLRT(fit, contrast = c(0,1,-1))
下面以MM
組和 WW
組的比較為例
topTags
提取出差異分析的數據;
decideTestsDGE
可以根據條件篩選差異基因,返回-1,0,1
三個數值,分別代表下調,不顯著和上調;
plotSmear
畫一個簡單的表達量與fold change的關系圖。
degs.res.1vs3 <- topTags(lrt.1vs3, n = Inf, adjust.method = 'BH', sort.by = 'PValue')
degs.res.1vs3[1:5, ]
## Coefficient: 1*mobGroupsMM -1*mobGroupsWW
## logFC logCPM LR PValue FDR
## 74 -10.364020 9.042115 130.95167 2.537092e-30 7.258620e-27
## 490 -6.043444 8.401692 119.28833 9.056111e-28 1.295477e-24
## 1717 -7.056255 9.921304 114.37749 1.077199e-26 1.027289e-23
## 1963 6.492175 6.868420 102.37925 4.584800e-24 3.279278e-21
## 1111 -9.565662 8.284244 97.26908 6.051792e-23 3.462836e-20
deGenes.1vs3 <- decideTestsDGE(lrt.1vs3, p=0.05, lfc = 1)
summary(deGenes.1vs3)
## 1*mobGroupsMM -1*mobGroupsWW
## Down 430
## NotSig 2094
## Up 337
detag <- rownames(lrt.1vs3)[as.logical(deGenes.1vs3)]
plotSmear(lrt.1vs3, de.tags=detag)
abline(h=c(-1, 1), col='blue')
圖中紅色的是統計學上的顯著差異表達基因
至于edgeR與DESeq2的比較其實已經有很多benchmark的文獻做過了,這里就先鴿一下,以后有機會再來填坑。
benchmark ref:https://bioconductor.org/packages/release/bioc/vignettes/SummarizedBenchmark/inst/doc/Feature-Iterative.html
參考文章:
完。