Lesson · 40 min · Free
scRNA-seq QC: Cell Filtering
scRNA-seq QC: Cell Filtering body { font-family: sans-serif; line-height: 1.6; margin: 20px; } h1, h2 { color: #2c3e50; } pre { background-color: #ecf0f1; padding: 15px; border-radius: 5px; overflow-x: auto; } code { fon
scRNA-seq QC: Cell Filtering
Welcome to this lesson on single-cell RNA sequencing (scRNA-seq) Quality Control (QC), specifically focusing on cell filtering . In scRNA-seq, the initial data often contains a mix of high-quality cells, damaged cells, empty droplets, and even multiplets (multiple cells captured in a single droplet). Effective cell filtering is a crucial first step to ensure downstream analysis is performed on biologically meaningful data, preventing erroneous conclusions driven by technical artifacts. The goal of cell filtering is to identify and remove cells that do not represent viable, intact, and single cells. This process typically involves setting thresholds based on several key metrics derived during the initial data processing. These metrics reflect the overall quality and integrity of each captured "cell" or droplet.
Key Metrics for Cell Filtering
Several standard metrics are commonly used to assess cell quality and inform filtering decisions: Number of Unique Molecular Identifiers (UMIs) per cell ( nFeature_RNA or nCount_RNA ): This metric represents the total number of distinct RNA molecules detected in a cell. Low UMI counts can indicate empty droplets, very small cells, or cells that were poorly captured. Conversely, extremely high UMI counts might suggest multiplets (two or more cells captured together) or unusually large cells. Number of Genes Detected per cell ( nFeature_RNA ): Similar to UMI counts, the number of genes detected reflects the transcriptional complexity of a cell. Low gene counts often point to low-quality cells or empty droplets, while very high gene counts might indicate multiplets. Percentage of Mitochondrial Reads ( percent.mt ): Mitochondria contain their own genome, and mitochondrial genes are transcribed. A high percentage of reads mapping to mitochondrial genes is a strong indicator of cell damage or stress. When a cell's plasma membrane is compromised, cytoplasmic RNA degrades faster than mitochondrial RNA, leading to an enrichment of mitochondrial transcripts. Healthy, intact cells typically have a low percentage of mitochondrial reads (often < 5-10%, though this can vary by cell type and tissue). Percentage of Ribosomal Reads ( percent.ribo ): Ribosomal genes are highly expressed in actively translating cells. While less universally used as a strict filter than mitochondrial reads, a very low or very high percentage of ribosomal reads could sometimes indicate cellular stress or specific cell states, respectively. The specific thresholds for these metrics are not universal and often depend on the cell type, tissue, sequencing depth, and experimental protocol. It's essential to visualize the distributions of these metrics (e.g., using violin plots or histograms) to make informed decisions about appropriate cutoffs. Here's an example using the Seurat package in R, a popular tool for scRNA-seq analysis. This code snippet demonstrates how to visualize these metrics and apply basic filtering: # Assuming 'pbmc.data' is a Seurat object after initial data loading # Visualize QC metrics VlnPlot(pbmc.data, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3) # FeatureScatter plots to visualize relationships between metrics plot1 <- FeatureScatter(pbmc.data, feature1 = "nCount_RNA", feature2 = "percent.mt") plot2 <- FeatureScatter(pbmc.data, feature1 = "nCount_RNA", feature2 = "nFeature_RNA") CombinePlots(plots = list(plot1, plot2)) # Apply filtering based on observed distributions # Example thresholds: # - Remove cells with < 200 unique features (genes) # - Remove cells with > 2500 unique features (potential multiplets) # - Remove cells with > 5% mitochondrial reads (damaged/dying cells) pbmc.filtered <- subset(pbmc.data, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5) print(paste("Original number of cells:", ncol(pbmc.data))) print(paste("Number of cells after filtering:", ncol(pbmc.filtered))) In Python, using the Scanpy library, a similar workflow can be followed: import scanpy as sc import matplotlib.pyplot as plt # Assuming 'adata' is an AnnData object after initial data loading # Calculate mitochondrial percentage (assuming mitochondrial genes start with 'MT-') adata.var['mt'] = adata.var_names.str.startswith('MT-') sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], percent_top=None, log1p=False, inplace=True) # Visualize QC metrics sc.pl.violin(adata, ['n_genes_by_counts', 'total_counts', 'pct_counts_mt'], jitter=0.4, multi_panel=True) plt.show() # Scatter plots for relationships sc.pl.scatter(adata, x='total_counts', y='pct_counts_mt') sc.pl.scatter(adata, x='total_counts', y='n_genes_by_counts') plt.show() # Apply filtering # Example thresholds: # - Remove cells with < 200 genes # - Remove cells with > 2500 genes # - Remove cells with > 5% mitochondrial reads adata_filtered = adata[adata.obs['n_genes_by_counts'] > 200] adata_filtered = adata_filtered[adata_filtered.obs['n_genes_by_counts'] < 2500] adata_filtered = adata_filtered[adata_filtered.obs['pct_counts_mt'] < 5] print(f"Original number of cells: {adata.n_obs}") print(f"Number of cells after filtering: {adata_filtered.n_obs}") It's crucial to document the filtering criteria applied, as these decisions can significantly impact downstream analysis and biological interpretation. Always consider the biological context and experimental design when setting these thresholds.
Key Takeaways
Cell filtering is a critical initial step in scRNA-seq QC to remove low-quality cells and artifacts. Key metrics for filtering include the number of UMIs/genes detected and the percentage of mitochondrial reads. Low UMI/gene counts often indicate empty droplets or poor capture; high counts can suggest multiplets. High mitochondrial read percentages are a strong indicator of damaged or dying cells. Thresholds for filtering should be determined empirically by visualizing metric distributions and considering the experimental context.
Practice Exercise
Imagine you are analyzing a scRNA-seq dataset from human neuronal cells. After initial data loading, you generate violin plots for nFeature_RNA , nCount_RNA , and percent.mt . You observe that the percent.mt distribution shows a clear bimodal peak, one around 3% and another broader peak extending from 15% to 40%. For nFeature_RNA , most cells fall between 500 and 3000 features, but there's a tail of cells with < 200 features and a few outliers with > 6000 features. Based on this information, describe the filtering strategy you would propose, justifying your choices for each metric. What potential artifacts are you trying to remove with each cutoff?
Watch the full lesson — free
This topic is part of Bioinformatics & Computational Genomics, a complete AI-narrated video course. Press play once and watch the entire lecture like a movie.
Start the course free →