Single-cell RNA-seq analysis in R with Seurat v5 — QC, normalization (LogNormalize or SCTransform), dimensionality reduction, clustering, marker detection, integration of multiple samples, and interconversion with AnnData/scanpy. Use when single-cell work must stay in R/Bioconductor, when collaborators expect a Seurat object, or when following an R-based tutorial. For Python single-cell workflows use scanpy/anndata instead.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add stanfish06/skillquarium --skill seurat --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Seurat?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/stanfish06-seurat)More formats (shields.io, HTML) on the badges page.
---
name: seurat
description: Single-cell RNA-seq analysis in R with Seurat v5 — QC, normalization (LogNormalize or SCTransform), dimensionality reduction, clustering, marker detection, integration of multiple samples, and interconversion with AnnData/scanpy. Use when single-cell work must stay in R/Bioconductor, when collaborators expect a Seurat object, or when following an R-based tutorial. For Python single-cell workflows use scanpy/anndata instead.
---
# Seurat (R) — single-cell RNA-seq
## Overview
Seurat (Satija lab) is the dominant **R** toolkit for single-cell/spatial analysis. Use it
when the analysis must live in R (Bioconductor downstream, R-based collaborators, lab
convention) — otherwise [[scanpy]]/[[anndata]] in Python is the equivalent and is already
well covered in this vault. Seurat v5 introduced the layered `Assay5` object and a
`BPCells`-backed on-disk path for very large datasets.
## When to use vs scanpy
- **Seurat** — R/tidyverse/Bioconductor downstream, integration with `DESeq2`/`edgeR`
pseudobulk, `SingleR` annotation, established lab pipelines.
- **scanpy** — Python ecosystem, scVI/deep models ([[scvi-tools]]), very large atlases,
AnnData-native tooling.
Convert between them rather than re-running: use `sceasy`, `zellkonverter`
(`SingleCellExperiment` ↔ AnnData), or `SeuratDisk` (`.h5Seurat` ↔ `.h5ad`).
## Standard workflow
```r
library(Seurat)
# 1. Load (10x output) and create object with basic gene/cell filters
counts <- Read10X(data.dir = "filtered_feature_bc_matrix/")
obj <- CreateSeuratObject(counts, min.cells = 3, min.features = 200)
# 2. QC: mitochondrial fraction, then filter
obj[["percent.mt"]] <- PercentageFeatureSet(obj, pattern = "^MT-") # "^mt-" for mouse
VlnPlot(obj, c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)
obj <- subset(obj, nFeature_RNA > 200 & nFeature_RNA < 6000 & percent.mt < 15)
# 3a. Standard normalization path
obj <- NormalizeData(obj)
obj <- FindVariableFeatures(obj, nfeatures = 2000)
obj <- ScaleData(obj)
# 3b. OR SCTransform (preferred; replaces NormalizeData+FindVariableFeatures+ScaleData)
# obj <- SCTransform(obj, vars.to.regress = "percent.mt")
# 4. Linear + non-linear dim reduction, graph clustering
obj <- RunPCA(obj)
ElbowPlot(obj) # choose #PCs
obj <- FindNeighbors(obj, dims = 1:30)
obj <- FindClusters(obj, resolution = 0.5) # higher res -> more clusters
obj <- RunUMAP(obj, dims = 1:30)
DimPlot(obj, reduction = "umap", label = TRUE)
# 5. Marker genes
markers <- FindAllMarkers(obj, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
FeaturePlot(obj, c("CD3D", "MS4A1", "LYZ"))
saveRDS(obj, "obj.rds")
```
## Integration (multiple samples / batch correction)
Seurat v5 unifies integration under `IntegrateLayers`. Split layers by batch first:
```r
obj[["RNA"]] <- split(obj[["RNA"]], f = obj$sample)
obj <- NormalizeData(obj) |> FindVariableFeatures() |> ScaleData() |> RunPCA()
obj <- IntegrateLayers(obj, method = CCAIntegration, # or HarmonyIntegration,
orig.reduction = "pca", # RPCAIntegration,
new.reduction = "integrated.cca") # scVIIntegration
obj <- FindNeighbors(obj, reduction = "integrated.cca", dims = 1:30)
obj <- FindClusters(obj); obj <- RunUMAP(obj, reduction = "integrated.cca", dims = 1:30)
obj <- JoinLayers(obj) # re-join before DE / pseudobulk
```
`HarmonyIntegration` mirrors [[harmonypy]]; `RPCA` is faster/more conservative than `CCA`
for large or weakly-overlapping datasets.
## Gotchas
- **v5 layers:** counts/data/scale.data are now *layers*. After integration, call
`JoinLayers()` before differential expression or pseudobulk, or you'll operate per-batch.
- **SCTransform + markers:** run `PrepSCTFindMarkers()` before `FindMarkers` on SCT data.
- **Species mito pattern:** `^MT-` (human) vs `^mt-` (mouse); a wrong pattern silently
yields `percent.mt == 0` and bad QC.
- **Pseudobulk DE** beats single-cell Wilcoxon for condition contrasts: aggregate with
`AggregateExpression()`/`Seurat::PseudobulkExpression()` then hand off to [[pydeseq2]] or
edgeR. See [[de-summary]] for interpreting results.
- **Memory:** for >500k cells use the `BPCells` on-disk backend or switch to [[scanpy]].
## Related
R counterpart to [[scanpy]]/[[anndata]]; integrate with [[harmonypy]], [[scvi-tools]]
(via `scVIIntegration`), [[bioconductor-bridge]], and pseudobulk DE via [[pydeseq2]].
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!