單細胞交響樂12-檢測Doublet

劉小澤寫於2020.7.15
爲何取名叫“交響樂”?因爲單細胞分析就像一個大樂團,需要各個流程的協同配合
單細胞交響樂1-常用的數據結構SingleCellExperiment
單細胞交響樂2-scRNAseq從實驗到下游簡介
單細胞交響樂3-細胞質控
單細胞交響樂4-歸一化
單細胞交響樂5-挑選高變化基因
單細胞交響樂6-降維
單細胞交響樂7-聚類分羣
單細胞交響樂8-marker基因檢測
單細胞交響樂9-細胞類型註釋
單細胞交響樂10-數據集整合後的批次矯正
單細胞交響樂11-多樣本間差異分析

1 前言

scRNA中,doublets指的就是一個文庫中存在兩個細胞的情況。一般是由於技術誤差導致的(比如細胞分選、捕獲),尤其在基於液滴的技術中(例如10X)比較突出。它干擾了對單個細胞表達量以及細胞形態的判斷,比如一個液滴中有兩個細胞,會通過誤導我們這個細胞可能處於分化的“過渡態”。因此檢測和去除這部分的影響至關重要。

一個比較通用的檢測方法是:單純根據表達量(Dahlin et al. 2018)。下面將利用一個10X數據來展示兩種檢測方法,它們的主要區別是我們是否需要提前知道分羣的信息

數據準備

#--- loading ---#
library(scRNAseq)
sce.mam <- BachMammaryData(samples="G_1")

#--- gene-annotation ---#
library(scater)
rownames(sce.mam) <- uniquifyFeatureNames(
    rowData(sce.mam)$Ensembl, rowData(sce.mam)$Symbol)

library(AnnotationHub)
ens.mm.v97 <- AnnotationHub()[["AH73905"]]
rowData(sce.mam)$SEQNAME <- mapIds(ens.mm.v97, keys=rowData(sce.mam)$Ensembl,
    keytype="GENEID", column="SEQNAME")

#--- quality-control ---#
is.mito <- rowData(sce.mam)$SEQNAME == "MT"
stats <- perCellQCMetrics(sce.mam, subsets=list(Mito=which(is.mito)))
qc <- quickPerCellQC(stats, percent_subsets="subsets_Mito_percent")
sce.mam <- sce.mam[,!qc$discard]

#--- normalization ---#
library(scran)
set.seed(101000110)
clusters <- quickCluster(sce.mam)
sce.mam <- computeSumFactors(sce.mam, clusters=clusters)
sce.mam <- logNormCounts(sce.mam)

#--- variance-modelling ---#
set.seed(00010101)
dec.mam <- modelGeneVarByPoisson(sce.mam)
top.mam <- getTopHVGs(dec.mam, prop=0.1)

#--- dimensionality-reduction ---#
library(BiocSingular)
set.seed(101010011)
sce.mam <- denoisePCA(sce.mam, technical=dec.mam, subset.row=top.mam)
sce.mam <- runTSNE(sce.mam, dimred="PCA")

#--- clustering ---#
snn.gr <- buildSNNGraph(sce.mam, use.dimred="PCA", k=25)
colLabels(sce.mam) <- factor(igraph::cluster_walktrap(snn.gr)$membership)

sce.mam
## class: SingleCellExperiment 
## dim: 27998 2772 
## metadata(0):
## assays(2): counts logcounts
## rownames(27998): Xkr4 Gm1992 ... Vmn2r122 CAAA01147332.1
## rowData names(3): Ensembl Symbol SEQNAME
## colnames: NULL
## colData names(5): Barcode Sample Condition sizeFactor label
## reducedDimNames(2): PCA TSNE
## altExpNames(0):

或者直接加載做好的數據:https://share.weiyun.com/ReZZnAMw

2 兩種檢測方法

2.1 基於分羣結果的檢測

使用doubletCluster() 將任一cluster與其他另外兩個clusters的表達量進行比較,即3個cluser爲一組,其中一個是query,另外兩個是source。基於的原假設是:query cluster的細胞中如果包含doublet,那麼它是來自兩個source clusters。 (Bach et al. 2017)

參考幫助文檔,它的具體做法是:
For each “query” cluster, we examine all possible pairs of “source” clusters, hypothesizing that the query consists of doublets formed from the two sources.

If so, gene expression in the query cluster should be strictly intermediate between the two sources after library size normalization.

library(scran)
# sce.mam一共分了10羣,所以下面的結果也是10行,每一羣都做了一次檢測
> table(sce.mam$label)

  1   2   3   4   5   6   7   8   9  10 
550 799 716 452  24  84  52  39  32  24 

dbl.out <- doubletCluster(sce.mam)
> dim(dbl.out)
[1] 10  9

返回的結果包括:

  • 基因數量N:query cluster與另外兩個source cluster相比特有的差異基因,它的數量多少可以爲拒絕原假設提供依據。這個基因數量越少,query越有可能是doublets
  • 文庫大小比例 lib.size:每個source cluster的各個細胞文庫大小中位數 / query cluster中的各個細胞文庫大小中位數,因此兩個source就對應兩個lib.size。我們知道doublets是一個文庫包含兩個細胞,因此它會比單個細胞的文庫更大。這個值越小,query越可能是doublets
  • 佔全部細胞的百分比 prop:query中的細胞數量佔全部細胞的百分比,一般這個值小於5%,不過也取決於10X機器上樣的數量

最後主要還是看N的數量,可以將這個結果按照N排個序

library(scater)
chosen.doublet <- rownames(dbl.out)[isOutlier(dbl.out$N, 
    type="lower", log=TRUE)]
chosen.doublet
## [1] "6"

挑出來懷疑對象,可以對cluster6進一步檢查

比如找到cluster6的marker基因

markers <- findMarkers(sce.mam, direction="up")
dbl.markers <- markers[[chosen.doublet]]
> dim(dbl.markers)
[1] 27998    13
# 然後找Top10基因
library(scater)
chosen <- rownames(dbl.markers)[dbl.markers$Top <= 10]
> length(chosen)
[1] 43
# 最後熱圖
plotHeatmap(sce.mam, order_columns_by="label", features=chosen, 
    center=TRUE, symmetric=TRUE, zlim=c(-5, 5))

看到這個cluster的marker基因,是不是在它的source cluster(即cluster1、2)中也有類似的表達模式?

另外,基於背景知識,沒有細胞會同時表達basal cells (Acta2) and alveolar cells (Csn2) 這兩個基因,但是看到cluster6中這兩個基因表達量都較高,再一次證明了我們的假設:cluster6是一個doublet混合體,而不是純粹的一個細胞類型

plotExpression(sce.mam, features=c("Acta2", "Csn2"), 
    x="label", colour_by="label")
注意

從上面也能看到,doubletCluster()的優點就是方便操作,並且結果比較好理解。一旦有懷疑的cluster,就可以立即檢查。但缺點是高度依賴分羣的質量,如果分羣不好,那麼這個結果的可信度就會大打折扣。另外,如果真的有某個亞羣中細胞數量很少,帶來的結果就是:N小,讓這個亞羣很有可能成爲懷疑對象。

不過,隨着scRNA的技術改進,這個doublets情況會逐漸好轉

2.2 基於模擬推斷的檢測

將利用來自scran包的doubletCells() ,它基於的假設是:模擬的doublets和真實的doublets接近

它的算法是:

  • 隨機選取兩個原始單細胞表達量,加和,當做一個模擬的doublet,這樣操作上千次
  • 對每一個原始細胞,看看它附近有多少的模擬的doublet,並計算密度
  • 對每一個原始細胞,同時計算它附近的其他原始細胞的數量,並計算密度
  • 對每一個細胞,計算兩個密度的比值,作爲“doublet score”

爲了加快密度的計算,這個函數會進行一個PCA以及log轉換

library(BiocSingular)
set.seed(100)

dbl.dens <- doubletCells(sce.mam, subset.row=top.mam, 
    d=ncol(reducedDim(sce.mam)))
summary(dbl.dens)
##     Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
##     0.00     7.63    21.04   395.42    49.30 39572.52

然後把計算結果的doublet score畫出來,數值較高的細胞聚成一團

sce.mam$DoubletScore <- log10(dbl.dens+1)
plotTSNE(sce.mam, colour_by="DoubletScore")

同時,結合之前doubletCluster()的結果看一眼:多麼明顯的cluster6!

注意

doubletCells() 的優點就是不需要依賴分羣結果,降低了分羣的影響。缺點是需要對doublets的模擬更精確,真的要保證它和真實的情況接近。

另外簡單去掉那些doublet scores較高的細胞有時也是不夠的,例如一個潛在的doublet cluster中只有一小部分的分值高,去掉它們剩下的細胞依然會干擾判斷。那麼問題來了,怎麼樣才叫高的doublet scores呢?是不是得設置一個閾值?就像剛纔這種情況,如果把閾值降低會不會就多包括了一些潛在的doublets呢?其實這也是生信中的一個比較頭疼的問題,沒有一個固定的閾值或者範圍,一切都是相對的。

比較推薦的方法是將doubletCells() 的結果再用分羣展示出來,就像上面的圖,可以更直觀看到那些細胞影響較大。

小結

  • 檢測doublet操作必須要求數據來自同一批次,因爲doublet也不會來自兩次捕獲的細胞,它畢竟是一個文庫,只是包含兩個細胞,因此也不需要擔心檢測doublet時怎麼去除批次效應之類的問題。最好還是在分析前最好先清楚實驗設計
  • 如果數據中包含了細胞分化軌跡的信息,doublet就不好判斷了,因爲處於變化狀態的細胞就很像doublet,容易被誤認

歡迎關注我們的公衆號~_~  
我們是兩個農轉生信的小碩,打造生信星球,想讓它成爲一個不拽術語、通俗易懂的生信知識平臺。需要幫助或提出意見請後臺留言或發送郵件到[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章