Chapter 1 Quality Control
1 (Lun 2018).
- They interfere the problematic cells at the start of the analysis. This step is commonly referred to as quality control (QC) on the cells. (We will use “library” and “cell” rather interchangeably here, though the distinction will become important when dealing with droplet-based data.) We demonstrate using a small scRNA-seq dataset ## colnames(192): SLX-9555.N701_S502.C89V9ANXX.s_1.r_1 ## SLX-9555.N701_S503.C89V9ANXX.s_1.r_1 ... ## SLX-11312.N712_S508.H5H5YBBXX.s_8.r_1 ## SLX-11312.N712_S517.H5H5YBBXX.s_8.r_1 ## colData names(9): Source Name cell line ... spike-in addition block ## reducedDimNames(0): ## mainExpName: endogenous ## altExpNames(2): ERCC SIRV
1.2 Common choices.
Finally, the
altexps_ERCC_percent column contains the percentage of reads mapped to ERCC transcripts.
# Identifying the mitochondrial transcripts in our SingleCellExperiment. location <- rowRanges(sce.416b) is.mito <- any(seqnames(location)=="MT") library(scuttle) df <- perCellQCMetrics(sce.416b, subsets=list(Mito=is.mito)) summary(df$sum)
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 27084 856350 1111252 1165865 1328301 4398883
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 5609 7502 8341 8397 9208 11380
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 4.59 7.29 8.14 8.15 9.04 15.62
## Min. 1st Qu. Median Mean 3rd Qu. Max. ## 2.24 4.29 6.03 6.41 8.13 19.43 diagnostic plots described in Section 1.4 and Advanced Section 1.5.
1.3 Identifying low-quality cells
1.3.1 With fixed thresholds
The simplest approach to identifying low-quality cells involves applying fixed thresholds.
1.3.2 With adaptive thresholds
Here, we assume that most of the dataset consists of high-quality cells.
We then identify cells that are outliers for the various QC metrics, based on the median absolute deviation (MAD) from the median value of each metric across all cells.
By default, we consider a value to be an outlier if it is more than 3 MADs from the median in the “problematic” direction.
This is loosely motivated by the fact that such a filter will retain 99% of non-outlier values that follow a normal distribution.
We demonstrate by using the
perCellQCFilters() function on the QC metrics from the 416B dataset.
reasons <- perCellQCFilters(df, sub.fields=c("subsets_Mito_percent", "altexps_ERCC_percent")) colSums(as.matrix(reasons))
## low_lib_size low_n_features high_subsets_Mito_percent ## 4 0 2 ## high_altexps_ERCC_percent discard ## 1 6
This function will identify cells with log-transformed library sizes that are more than 3 MADs below the median.
A log-transformation is used to improve resolution at small values when
type="lower"
and to avoid negative thresholds that.)
The function will also do the same for the log-transformed number of expressed genes.
perCellQCFilters() will also identify outliers for the proportion-based metrics specified in the
sub.fields= arguments..)
A cell that is an outlier for any of these metrics is considered to be of low quality and discarded.
This is captured in the
discard column, which can be used for later filtering (Section 1.5).
## Mode FALSE TRUE ## logical 186 6
We can also extract the exact filter thresholds from the attributes of each of the logical vectors. This may be useful for checking whether the automatically selected thresholds are appropriate.
## lower higher ## 434083 Inf
## lower higher ## 5231 Inf, the underlying assumption of a high-quality majority may not always be appropriate, which is discussed in more detail in Advanced Section 1.3.
1 180 12.
1.4 Checking diagnostic plots
It is good practice to inspect the distributions of QC metrics (Figure 1 library(scater) 1 1.2 that might potentially correspond to metabolically active, undamaged cells.
#--- loading ---# library(scRNAseq) sce.zeisel <- ZeiselBrainData() library(scater) sce.zeisel <- aggregateAcrossFeatures(sce.zeisel, id=sub("_loc[0-9]+$", "", rownames(sce.zeisel))) #--- gene-annotation ---# library(org.Mm.eg.db) rowData(sce.zeisel)$Ensembl <- mapIds(org.Mm.eg.db, keys=rownames(sce.zeisel), keytype="SYMBOL", column="ENSEMBL") 1.2: 1 1 inadvertently discarding entire cell types.
1 1.3.2 to generate a subsetted
SingleCellExperiment that we would use for downstream analyses., deferring the decision on whether a cluster of such cells represents a genuine biological state.
The downside is that it shifts the burden of QC to the manual interpretation of the clusters, which is already a major bottleneck in scRNA-seq data analysis (Chapters 5, 6 and 7). Indeed, if we do not trust the QC metrics, we would have to distinguish between genuine cell types and low-quality cells based only on marker genes, and this is not always easy due to the tendency of the latter to “express” interesting genes (Section 1 (Advanced Section 1.5), a more thorough re-analysis can be performed where the low-quality cells are only marked. This recovers cell types with low RNA content, high mitochondrial proportions, etc. that only need to be interpreted insofar as they “fill the gaps” in the initial analysis.
Session Info stats graphics grDevices utils datasets methods [8] base other attached packages: [1] scater_1.22.0 ggplot2_3.3.5 [3] robustbase_0.93-9 scuttle_1.4.0 [5] SingleCellExperiment_1.16.0 SummarizedExperiment_1.24.0 [7] Biobase_2.54.0 GenomicRanges_1.46.0 [9] GenomeInfoDb_1.30.0 IRanges_2.28.0 [11] S4Vectors_0.32.0 BiocGenerics_0.40.0 [13] MatrixGenerics_1.6.0 matrixStats_0.61.0 [15] BiocStyle_2.22.0 rebook_1.4.0 loaded via a namespace (and not attached): [1] bitops_1.0-7 filelock_1.0.2 [3] tools_4.1.1 bslib_0.3.1 [5] utf8_1.2.2 R6_2.5.1 [7] irlba_2.3.3 vipor_0.4.5 [9] DBI_1.1.1 colorspace_2.0-2 [11] withr_2.4.2 tidyselect_1.1.1 [13] gridExtra_2.3 compiler_4.1.1 [15] graph_1.72.0 BiocNeighbors_1.12.0 [17] DelayedArray_0.20.0 labeling_0.4.2 [19] bookdown_0.24 sass_0.4.0 [21] scales_1.1.1 DEoptimR_1.0-9 [23] rappdirs_0.3.3 stringr_1.4.0 [25] digest_0.6.28 rmarkdown_2.11 [27] XVector_0.34.0 pkgconfig_2.0.3 [29] htmltools_0.5.2 sparseMatrixStats_1.6.0 [31] highr_0.9 fastmap_1.1.0 [33] rlang_0.4.12 DelayedMatrixStats_1.16.0 [35] farver_2.1.0 jquerylib_0.1.4 [37] generics_0.1.1 jsonlite_1.7.2 [39] BiocParallel_1.28.0 dplyr_1.0.7 [41] RCurl_1.98-1.5 magrittr_2.0.1 [43] BiocSingular_1.10.0 GenomeInfoDbData_1.2.7 [45] Matrix_1.3-4 Rcpp_1.0.7 [47] ggbeeswarm_0.6.0 munsell_0.5.0 [49] fansi_0.5.0 viridis_0.6.2 [51] lifecycle_1.0.1 stringi_1.7.5 [53] yaml_2.2.1 zlibbioc_1.40.0 [55] grid_4.1.1 parallel_4.1.1 [57] ggrepel_0.9.1 crayon_1.4.1 [59] dir.expiry_1.2.0 lattice_0.20-45 [61] cowplot_1.1.1 beachmat_2.10.0 [63] CodeDepends_0.6.5 knitr_1.36 [65] pillar_1.6.4 codetools_0.2-18 [67] ScaledMatrix_1.2.0 XML_3.99-0.8 [69] glue_1.4.2 evaluate_0.14 [71] BiocManager_1.30.16 vctrs_0.3.8 [73] gtable_0.3.0 purrr_0.3.4 [75] assertthat_0.2.1 xfun_0.27 [77] rsvd_1.0.5 viridisLite_0.4.0 [79] tibble_3.1.5 beeswarm_0.4.0 [81] ellipsis_0.3.2
References.
Lun, A. T. L., F. J. Calero-Nieto, L. Haim-Vilmovsky, B. Gottgens, and J. C. Marioni. 2017. “Assessing the reliability of spike-in normalization for analyses of single-cell RNA sequencing data.” Genome Res. 27 (11): 1795–1806.
McCarthy, D. J., K. R. Campbell, A. T. Lun, and Q. F. Wills. 2017. “Scater: pre-processing, quality control, normalization and visualization of single-cell RNA-seq data in R.” Bioinformatics 33 (8): 1179–86.
Zeisel, A., A. B. Munoz-Manchado, S. Codeluppi, P. Lonnerberg, G. La Manno, A. Jureus, S. Marques, et al. 2015. “Brain structure. Cell types in the mouse cortex and hippocampus revealed by single-cell RNA-seq.” Science 347 (6226): 1138–42.