關于sva包
sva的用戶說明:http://www.bioconductor.org/packages/release/bioc/vignettes/sva/inst/doc/sva.pdf
其中關于去除批次效應的函數有Combat和Combat_seq兩個,而Combat主要面對的是帶有小數的數據(比方說芯片數據),基于的是貝葉斯原理;而Combat_seq主打RNA-seq的count數據,基于負二項分布回歸
Combat
測試數據的設計矩陣為:
表達矩陣為:
按照說明書那樣,我們需要事先知道這些batch的變量類型
# 提取batch的信息
batch = pheno$batch
# 建立對照組模型,這不也可以省略
modcombat = model.matrix(~1, data=pheno)
# 去除批次效應
combat_edata1 = ComBat(dat=edata, batch=batch, mod=NULL, par.prior=TRUE, prior.plots=FALSE)
這樣返回的就是去除批次效應后的數據了
而Combat函數的核心代碼:
# 輸入數據
dat=edata
batch=batch
mod = NULL ## 忽略設計矩陣
par.prior = TRUE
prior.plots = FALSE
mean.only = FALSE
ref.batch = NULL
# 定義出批次效應的項
batch <- as.factor(batch)
# dat 為表達矩陣,s.data相當于標準化后的表達矩陣
s.data <- (dat-stand.mean)/(sqrt(var.pooled) %*% t(rep(1,n.array)))
# 找到相同levels的sample,并歸類
n.batch <- nlevels(batch)
batches <- list()
for (i in 1:n.batch) {
## 把相同 levels 的 sample 歸為一類,即 batches[[1]] 代表所有levels = 1 的sample
batches[[i]] <- which(batch == levels(batch)[i])
} # list of samples in each batch
# 計算去除批次效應的表達矩陣
bayesdata <- s.data
## batches 代表有批次效應的sample
## 所有有批次效應的sample需要扣除批次效應的影響
for (i in batches){
bayesdata[,i] <- (bayesdata[,i]-t(batch.design[i,]%*%gamma.star))/(sqrt(delta.star[j,])%*%t(rep(1,n.batches[j])))
### t(batch.design[i,]%*%gamma.star) 代表批次效應所引起的基因表達量的差異,這一部分是需要被扣除的
j <- j+1
}
# 最后乘上系數
bayesdata <- (bayesdata*(sqrt(var.pooled)%*%t(rep(1,n.array))))+stand.mean # FIXME
而這段代碼的理論部分來自于文章《Adjusting batch effects in microarray expression data using empirical Bayes methods》
文章對去除批次效應分為了三步:
step_1:Standardize the data
簡單分析下各個因素對表達量的影響
其中:
- Yijg 代表 gene g for sample j from batch i
- αg 代表 overall gene expression,即 gene g 在所有sample中平均表達量
- X 代表 a design matrix for sample conditions,代表實驗設計所制定的矩陣
- βg 代表對X矩陣的回歸系數,代表不同設計矩陣各個因素下的效應值
- X·βg 代表設計矩陣各個因素除平均表達量αg以外的額外的表達值,對于sample j (因素 j)最后加上 αg 則代表sample j 中 gene g 的表達量
- γig 代表 the additive and multiplicative batch effects of batch i for gene g
- δig 代表 the additive and multiplicative batch effects of batch i for gene g
由上面的公式結合代碼我們不難看出,此時忽略設計矩陣
## 定義設計矩陣
## combine batch variable and covariates
design <- cbind(batchmod,mod)
## batchmod為與batch有關的設計矩陣,mod為實驗設計矩陣
# 均值的計算
stand.mean <- stand.mean+t(tmp %*% B.hat)
# 方差的計算
var.pooled <- ((dat-t(design %*% B.hat))^2) %*% rep(1/n.array,n.array)
## B.hat代表β.hat
## tmp為與batch相關的設計矩陣,即與,如果不考慮實驗設計因素,那么tmp為0矩陣
Step_2: EB batch effect parameter estimates using parametric empirical priors
假設每一個元素所服從分布如下:
顯而易見的是經過標準化后的sample j 中 gene g 的表達量的不同,完全是由于批次效應所導致(因為標準化過程以及扣除均值αg,實驗設計的差異部分 X·βg 的影響,僅剩下批次效應的影響)
假設標準化后的表達矩陣里面的元素值 Zijg 服從正態分布,均值為 γig(γig為the additive and multiplicative batch effects of batch i for gene g),而這些參數估計需要用到貝葉斯后驗來進行估計
假設 γig 服從正態分布,這個假設我有點吐槽,萬一 γig(批次效應所引起的差異值)并不服從這種分布呢? 并且作者定義
為批次效應所引起的基因表達量的差異,這一部分是需要被扣除的
Step_3: Adjust the data for batch effects
由上面式子我們知道,最終去除批次效應結果的主體是標準化的數據減去批次效應所引起的基因表達量的差異而得
其中
帶帽的
Combat_seq
這個函數主打RNA-seq的count數據,而它的下載方式需要用:
# 下載方式
devtools::install_github("zhangyuqing/sva-devel")
# 示例數據
count_matrix <- matrix(rnbinom(400, size=10, prob=0.1),nrow=50, ncol=8)
batch <- c(rep(1, 4), rep(2, 4))
adjusted <- ComBat_seq(count_matrix, batch=batch, group=NULL)
我們參考這篇文獻來分析它的原理:《ComBat-Seq: batch effect adjustment for RNA-Seq count data》
Combat_seq基于的原理是負二項分布回歸
這里的負二項分布指的是基因的表達服從負二項分布,如下圖
橫坐標表示基因的表達量,縱坐標表示的是基因表達量在某個區間范圍內的頻率,那么整個count矩陣數據符合負二項分布,用具有這樣數據特點的矩陣做的回歸稱為負二項分布回歸
同樣的,它的基本模型也是線性模型,理解起來和Combat的是類似的
其中:
- μijg 代表 gene g for sample j from batch i
- αg 代表 overall gene expression,即 gene g 在所有sample中平均表達量
- Xj 代表 a design matrix for sample conditions,代表實驗設計所制定的矩陣
- βg 代表對X矩陣的回歸系數,代表不同設計矩陣各個因素下的效應值
- Xj·βg 代表設計矩陣各個因素除平均表達量αg以外的額外的表達值,對于sample j (因素 j)最后加上 αg 則代表sample j 中 gene g 的表達量
- γgi 代表批次效應 i 影響 gene g 的表達值從而產生差異的部分(均值)
- ** ?gi** 代表批次效應 i 影響 gene g 的表達值從而產生差異的部分(dispersion)
- Nj 代表文庫大小
而關于Combat_seq的核心代碼:
# 讀入相關的內容
## count_matrix為count矩陣
counts = count_matrix
## batch 為批次效應向量
batch=batch
group=NULL
covar_mod=NULL
full_mod=TRUE
shrink=FALSE
shrink.disp=FALSE
gene.subset.n=NULL
# 廣義線性模型擬合數據,即建立真實的基因表達量
## 這里的design代表的是batch的設計矩陣
## dge_obj$counts為counts矩陣
## 參數 phi_matrix 通過edgeR包中的函數estimateGLMCommonDisp進行估計
glm_f2 <- glmFit.default(dge_obj$counts, design=design, dispersion=phi_matrix,
offset=new_offset, prior.count=1e-4)
# gamma_hat 為glm_f2 模型的系數,代表不同batch對每個sample的影響
gamma_hat <- glm_f2$coefficients[, 1:n_batch]
# mu_hat為利用模型擬合的count值
mu_hat <- glm_f2$fitted.values
phi_hat <- do.call(cbind, genewise_disp_lst)
design矩陣的行為不同的sample1-8
而dge_obj$counts為counts矩陣,counts矩陣的行為不同的基因
前1-4個sample受到batch1的影響,后5-8個sample受到batch2的影響,由于batch的設計矩陣都是0,1型的因子變量,所以模型的系數就可以定義為γgi,即Xj·gamma_hat(X取值為0或1)對應的就是γgi(批次效應 i 影響 gene g 的表達值從而產生差異的部分)的值
然而去除批次效應所帶來影響需要將原始counts值,減去對應batch所帶來的影響γgi:
mu_star <- matrix(NA, nrow=nrow(counts), ncol=ncol(counts))
## mu_hat 可以理解為count值
## vec2mat(gamma_star_mat[, jj], n_batches[jj])可以理解為batch的效應值 γgi,只不過將它做成矩陣形式方便計算
for(jj in 1:n_batch){
## count值減去batch的效應值 γgi,最終得到去除批次效應的結果
mu_star[, batches_ind[[jj]]] <- exp(log(mu_hat[, batches_ind[[jj]]])-vec2mat(gamma_star_mat[, jj], n_batches[jj]))
}
最后對 mu_star 進行整數化的矯正就可以得到最終結果了:
行為基因,列為sample1-8