一、为什么要做质控?
在细胞分离过程中的细胞损伤或者文库制备的失败(无效的逆转录或者PCR扩增失败),往往会引入一些低质量的数据。这些低质量的数据的主要特点是:
如果这些损伤的行或者列,没有被移除的话,可能会对下游的分析结果产生影响。所以我们在进行分析之前,一定要率先移除这些低质量的行与列。(一开始的理解,后面整个流程做完之后,或许理解会更多,那么接下来在做详细的补充)
二、质控的基本流程
1、测试数据集的加载
library(scRNAseq)
example_sce <- ZeiselBrainData()
测试数据集的基本概况(尚未做QC处理):
class: SingleCellExperiment
dim: 20006 3005
metadata(0):
assays(1): counts
rownames(20006): Tspan12 Tshz1 … mt-Rnr1 mt-Nd4l
rowData names(1): featureType
colnames(3005): 1772071015_C02 1772071017_G12 … 1772066098_A12 1772058148_F03
colData names(10): tissue group # … level1class level2class
reducedDimNames(0):
altExpNames(2): ERCC repeat
2、质控的指标
在文库制备的过程中,可能因为细胞的裂解或cDNA捕获和扩招效率的低下,而使得RNA的丢失。具有较小的counts值之和的细胞被认为是低质量的细胞,考虑被去除。
多样化的转录本如果没有被成功的捕获到,因此任何一个细胞中有很少的基因表达,被认为是低质量的,考虑被去除。
每个细胞中添加的spike-in序列(人为添加的表达量的参照系)的浓度都是等量的。如果spike-in的比值很高,那么就意味着在实验的过程中,大量的转录本丢失。
同样的,线粒体基因的高比例,也意味着这可能是由于穿孔细胞的细胞质RNA丢失,从而产生低质量的细胞。理由是,在存在适度细胞损伤的情况下,细胞膜上的孔允许单个转录物分子外排(丢失),但过小而无法使线粒体逸出,从而导致线粒体转录物的相对富集。
3、计算上述指标的值
#注释线粒体基因(常规步骤)
#这一行代码是将线粒体基因的基因名全部提取了出来,为字符型的变量,为下面的计算线粒体基因的比例做准备(同样也可以添加ERCC等subset),这里是由于这个数据集中已有ERCC的altExp了,因此不重复操作。
is.mt<-grep("^mt", rownames(example_sce),value = T)
library(scater)
#计算质量表达的矩阵
df <- perCellQCMetrics(example_sce, subsets=list(Mito=is.mt))
得到的df,是一个包含有以上各计算参数的数据框。
DataFrame with 3005 rows and 12 columns
sum detected subsets_Mito_sum subsets_Mito_detected subsets_Mito_percent
1772071015_C02 22354 4871 774 23 3.462468
1772071017_G12 22869 4712 1121 27 4.901832
1772071017_A05 32594 6055 952 27 2.920783
1772071014_B06 33525 5852 611 28 1.822521
1772067065_H06 21694 4724 164 23 0.755969
… … … … … …
1772067059_B04 5707 2250 1122 29 19.660067
1772066097_D04 2574 1441 15 13 0.582751
1772063068_D01 4993 2001 978 24 19.587422
1772066098_A12 3099 1510 203 17 6.550500
1772058148_F03 6534 1809 2074 34 31.741659
altexps_ERCC_sum altexps_ERCC_detected altexps_ERCC_percent altexps_repeat_sum
1772071015_C02 6706 43 18.0070 8181
1772071017_G12 6435 46 15.6349 11854
1772071017_A05 6335 47 11.1238 18021
1772071014_B06 7032 43 12.8999 13955
1772067065_H06 5931 39 17.1908 6876
… … … … …
1772067059_B04 5390 45 32.7799 5346
1772066097_D04 5898 43 54.6972 2311
1772063068_D01 7248 40 35.5852 8127
1772066098_A12 5072 40 50.0988 1953
1772058148_F03 4128 42 29.2807 3436
altexps_repeat_detected altexps_repeat_percent total
1772071015_C02 419 21.9677 37241
1772071017_G12 480 28.8012 41158
1772071017_A05 582 31.6435 56950
1772071014_B06 512 25.5999 54512
1772067065_H06 363 19.9299 34501
… … … …
1772067059_B04 340 32.5123 16443
1772066097_D04 163 21.4319 10783
1772063068_D01 493 39.9008 20368
1772066098_A12 169 19.2908 10124
1772058148_F03 269 24.3723 14098
我们对上述得到的这个数据库的行,列表示的值进行解释。
行名: 1772071015_C02 、1772071017_G12 、1772071017_A05 、1772071014_B06 、1772067065_H06等,为每一个测序细胞的名称。
列名:
(1)sum :即是上文提到的,每一个细胞对应的总的counts数。
(2)detected:为满足特定阈值(基因的表达量)的基因的数目。
(3)subset_Mito_sum:为检测到的线粒体基因的counts数。
(4)subsets_Mito_detected:为满足阈值表达的线粒体基因的数目
(5)subsets_Mito_percent:线粒体基因的counts值占总counts值的比值
……ERCC、repeat的解释类似,不赘述。
将计算得到的QC的各项数值存放到SingleCellExperiment对象的colData中。
example_sce<- addPerCellQC(example_sce, subsets=list(Mito=is.mt))
查看,发现colData names变多了(由10变到22),添加成功。
example_sce
class: SingleCellExperiment
dim: 20006 3005
metadata(0):
assays(1): counts
rownames(20006): Tspan12 Tshz1 … mt-Rnr1 mt-Nd4l
rowData names(1): featureType
colnames(3005): 1772071015_C02 1772071017_G12 … 1772066098_A12 1772058148_F03
colData names(22): tissue group # … altexps_repeat_percent total
reducedDimNames(0):
altExpNames(2): ERCC repeat
4、识别低质量的细胞
(1)固定的阈值
最简单的方法就是设定一个固定的阈值,从而筛选出符合条件的细胞。(但是这种筛选的标准有时候觉得过于武断,是基于经验性的一种设定,在实际的情况下,如不同的实验体系中,阈值具有差异)
如,细胞文库大小小于100,000,基因的表达量少于5,000,spike-in的比例高于10%,线粒体基因的比例高于10%(或的关系)设定为低质量的细胞。
#low-quality
qc.lib <- df$sum < 1e5
qc.nexprs <- df$detected < 5e3
qc.spike <- df$altexps_ERCC_percent > 10
qc.mito <- df$subsets_Mito_percent > 10
discard <- qc.lib | qc.nexprs | qc.spike | qc.mito
# Summarize the number of cells removed for each reason.
DataFrame(LibSize=sum(qc.lib), NExprs=sum(qc.nexprs),
SpikeProp=sum(qc.spike), MitoProp=sum(qc.mito), Total=sum(discard))
各类阈值下筛出的细胞数量的统计,一共筛去3005个细胞**(一共才只有3005个细胞,也就是说按照这个阈值是全筛完了)**。
DataFrame with 1 row and 5 columns
LibSize NExprs SpikeProp MitoProp Total
1 3005 2294 2686 799 3005
(2)可变的阈值
这个阈值的可变性主要体现在,是以数据本身的特征为参照,从而设定参考阈值的。
一般而言,以该组数据的中位数向着错误方向偏差超过3MADs(median absolute deviation),作为基本的参照。
使用的是isOutlier()这个函数,低于阈值筛去,则type设定为lower;高于阈值筛去,则type设定为upper。
qc.lib2 <- isOutlier(df$sum, log=TRUE, type="lower")
qc.nexprs2 <- isOutlier(df$detected, log=TRUE, type="lower")
qc.spike2 <- isOutlier(df$altexps_ERCC_percent, type="higher")
qc.mito2 <- isOutlier(df$subsets_Mito_percent, type="higher")
#查看阈值
attr(qc.lib2, "thresholds")
attr(qc.nexprs2, "thresholds")
attr(qc.spike2, "thresholds")
attr(qc.mito2, "thresholds")
discard2 <- qc.lib2 | qc.nexprs2 | qc.spike2 | qc.mito2
DataFrame(LibSize=sum(qc.lib2), NExprs=sum(qc.nexprs2),
SpikeProp=sum(qc.spike2), MitoProp=sum(qc.mito2), Total=sum(discard2))
各类阈值下筛出的细胞数量的统计,一共筛去189个细胞 (可以看到与前面的固定阈值的筛选结果相比,筛去的细胞的数量大大减少)。
DataFrame with 1 row and 5 columns
LibSize NExprs SpikeProp MitoProp Total
1 0 3 65 128 189
需要注意的是,可变阈值这样的一种筛选方式是基于一定的假设条件的。
基本假设: a.大多数细胞的质量都是好的。
b.QC指标(即上文提到的sums,detected等等),与生物学的实验条件无关,是系统变量。
在一些特殊的生物体系之中,这些“假设”会不成立。
比如一个细胞群系中的细胞的异质性程度很高,存在一些细胞天生的RNA的表达量很少,或者线粒体基因的相对比值很高。那么这一部分细胞就很容易在处理的过程中,当做是低质量的细胞,被去除。
(3)批次效应的影响
批次效应在处理数据的过程中需要被考虑到。那么,怎么去鉴定一个数据集是否存在批次效应呢?
attr(discard.ercc2,“thresholds”)
D10 D17 D2 D3 D7
lower -Inf -Inf -Inf -Inf -Inf
higher 9.475052 7.599947 6.010975 9.475052 15.21696
#每一个批次,他的阈值是不一样的#考虑到不同的批次
attr(discard.ercc,“thresholds”)
D10 D17 D2 D3 D7
lower -Inf -Inf -Inf -Inf -Inf
higher 73.6107 7.599947 6.010975 113.1058 15.21696