Introduction
If you're starting a spatial transcriptomics project in 2026, you've probably run into the same fork in the road every single-cell person eventually hits: Seurat or Squidpy? Both are mature, well-maintained, and backed by active communities — but they come from different ecosystems (R vs Python) and take different philosophical approaches to spatial data.
This isn't a "which one is objectively better" post. It's a practical breakdown of where each tool actually shines, based on what each is built for — so you can pick the right one for your pipeline instead of just going with whatever your lab used last.
To make this concrete instead of just theoretical, I actually ran Squidpy's core spatial workflow end-to-end on a real public dataset (squidpy's mouse brain Visium demo) and reported the real numbers below — not just textbook claims.
Quick Comparison
| Seurat | Squidpy | |
|---|---|---|
| Language | R | Python |
| Core strength | scRNA-seq + spatial integration | Spatial-first, neighborhood/graph analysis |
| Best for | Labs already in R/Bioconductor ecosystem | Pipelines needing scanpy/AnnData compatibility |
| Spatial stats | Basic (SpatialFeaturePlot, cluster overlay) | Advanced (Moran's I, neighborhood enrichment, ligand-receptor via squidpy.gr) |
| Learning curve | Lower if you know R | Lower if you know scanpy |
| GitHub stars (as of 2026) | ~2.8k | ~580 |
| Integration | Seurat objects, SeuratDisk | AnnData, works natively with scvi-tools |
When Seurat Makes Sense
- Your lab's existing scRNA-seq pipeline is already in Seurat — switching ecosystems mid-project has a real cost
- You need quick, publication-ready spatial overlay plots without much custom code
- You're working with 10x Visium data and want the well-documented
Load10X_Spatial()workflow
library(Seurat)
library(SeuratData)
brain <- LoadData("stxBrain", type = "anterior1")
brain <- SCTransform(brain, assay = "Spatial", verbose = FALSE)
brain <- RunPCA(brain, assay = "SCT", verbose = FALSE)
brain <- FindNeighbors(brain, reduction = "pca", dims = 1:30, verbose = FALSE)
brain <- FindClusters(brain, verbose = FALSE)
SpatialDimPlot(brain, label = TRUE)
Real output from this run (Seurat 5.5.1, R 4.6.1, SeuratData's stxBrain mouse brain Visium dataset — the official Seurat demo, conceptually the same tissue type as the squidpy demo below):
- Dataset loaded: 31,053 genes × 2,696 spots
SCTransformtook ~273 seconds (4.5 minutes) on this machine- Clustering (
FindNeighbors+FindClusters) took only ~3.4 seconds after that — the bottleneck is entirely in SCTransform, not clustering - 15 clusters were identified, matching well with visually distinct anatomical regions in the tissue image
- One real gotcha we hit: SCTransform printed a warning that it couldn't find the
glmGamPoipackage and fell back to a slower native implementation. InstallingglmGamPoivia Bioconductor first is a meaningful speedup for anyone running this regularly — we didn't have it installed for this run, which is reflected in the ~273s figure above.
Seurat's spatial cluster plot on the official stxBrain demo dataset — real output from the code above, not a mockup.
(This workflow follows Seurat's official Visium tutorial structure — Seurat workflows for Visium data are extensively documented and battle-tested across thousands of published studies, which is itself part of Seurat's value: you're rarely the first person debugging a given step.)
When Squidpy Makes Sense
- You need actual spatial statistics — neighborhood enrichment, co-occurrence, Moran's I autocorrelation — not just visualization
- Your downstream pipeline is Python-based (e.g., feeding into scvi-tools or a custom ML model)
- You're working with multiple spatial modalities (Visium, MERFISH, Xenium) and want one consistent API via AnnData
import squidpy as sq
import scanpy as sc
# Built-in public demo dataset (mouse brain, Visium)
adata = sq.datasets.visium_hne_adata()
sq.gr.spatial_neighbors(adata)
sq.gr.nhood_enrichment(adata, cluster_key="cluster")
sq.gr.co_occurrence(adata, cluster_key="cluster")
Spatial distribution of the 15 annotated brain regions, plotted directly from the squidpy run above.
Real output from this run (squidpy 1.x, mouse brain Visium demo dataset, 2,688 spots × 18,078 genes, 15 annotated regions including Cortex_1–5, Hippocampus, Thalamus_1–2, Striatum, etc.):
spatial_neighbors+nhood_enrichmentcompleted in ~9.5 seconds on the full 2,688-spot datasetco_occurrencecompleted in ~6.7 seconds- Neighborhood enrichment z-scores ranged up to ~78, meaning some region pairs (e.g. cortical layers next to each other) show very strong spatial co-localization — exactly the kind of signal Seurat's basic spatial plots won't quantify for you directly
- One practical gotcha I hit:
sq.gr.spatial_neighborsthrows aFutureWarningas of squidpy 1.x — it's being split intospatial_neighbors_knn/_radius/_delaunay/_gridin v1.9. If you're starting a new project now, it's worth using the specific function instead of the generic one to avoid a breaking change later.
Neighborhood enrichment z-scores between region pairs — darker/brighter cells indicate stronger spatial co-localization.
(Tested on squidpy's public demo dataset, not proprietary research data — same workflow applies to your own Visium/MERFISH/Xenium data via sq.read.visium() or the equivalent reader.)
The Honest Answer
If you're already deep in the R/Bioconductor world and just need solid visualization + basic spatial clustering, Seurat won't slow you down. If your work leans toward quantitative spatial statistics or you're building anything that touches a Python ML stack, Squidpy's purpose-built spatial functions save you from reinventing the wheel.
Based on actually running the Squidpy workflow above, the value isn't in the plots — it's in the quantified output (z-scores, co-occurrence stats) you can directly use in a paper or downstream model. That's the gap Seurat's spatial functions don't close on their own.
FAQ
Can I use both in the same project?
Yes — many labs preprocess in Seurat, export via SeuratDisk to AnnData, then run Squidpy's spatial stats.
Does Squidpy work with non-10x platforms like MERFISH or Xenium? Yes, Squidpy has built-in readers for multiple spatial platforms, which is one of its main advantages over Seurat's more Visium-centric workflow.
Is one faster than the other for large datasets?
We ran both on a similar-sized dataset (~2,700 spots) on the same machine. Squidpy's spatial graph + neighborhood enrichment finished in under 10 seconds. Seurat's SCTransform alone took ~273 seconds, though clustering after that was fast (~3.4s). Important caveat: these aren't doing identical work — SCTransform is a normalization step with no direct Squidpy equivalent in our comparison, so this isn't a clean apples-to-apples benchmark, just real numbers from real runs of each tool's typical workflow. Installing glmGamPoi would likely cut Seurat's SCTransform time significantly; we ran without it.
Last updated: June 2026. Tool versions referenced: Seurat 5.x, Squidpy 1.x — always check current documentation as APIs evolve.
Get the complete pack
Squidpy Complete Analysis Pack — 10 Notebooks
All 10 notebooks from this series in one download — SVGs, neighborhood enrichment, co-occurrence, ligand-receptor, and the complete pipeline. Verified and ready to run on your own data.
Get it for $19 →
No comments:
Post a Comment