Clustering: finding communities in a neighbour graph
Clustering groups cells with similar expression. Seurat does not split cells directly by their coordinates; it first builds a neighbour network in PC space, then looks for tightly connected communities in that network. The resolution parameter decides how finely the communities are cut.
From neighbours to communities
The first step is FindNeighbors: in the space of the leading PCs, each cell is linked to its k closest cells (k = 20 by default in Seurat), forming a k-nearest-neighbour graph. Seurat then weights each link by how many neighbours the two cells share, giving the SNN graph. The more neighbours two cells share, the stronger their link.
The second step is FindClusters: community detection on this graph, looking for groups of cells densely connected inside and sparsely connected to each other, by maximising “modularity”. Two algorithms are common: Seurat’s default is Louvain; Leiden is an improved version that guarantees each community is internally connected. Scanpy and OmicOne default to Leiden.
obj <- FindNeighbors(obj, dims = 1:10)
obj <- FindClusters(obj, resolution = 0.5)
Resolution sets the number of clusters
Resolution is a parameter in the modularity formula: the larger it is, the more the algorithm favours small communities, and the more clusters you get. Drag it from 0.1 to 1.5 in the widget and watch clusters merge and split on the UMAP while the count changes. As in the Seurat tutorial, the widget’s clusters come from Louvain on the first 10 PCs, and resolution 0.5 gives 9 clusters. A common pattern: at low resolution the T cells form one large group; as resolution rises, naive CD4, memory CD4 and CD8 subsets gradually separate.
There is no correct resolution. The Seurat tutorial suggests 0.4–1.2 for data of about 3,000 cells, and the pbmc3k tutorial uses 0.5. The choice depends on your question: for broad classes, use a low value; for subsets, first separate the lineages at low resolution, then re-cluster one lineage on its own. A practical check is whether splits are stable across neighbouring resolutions, and whether each new cluster has markers of its own.
Common pitfalls
- Equating clusters with cell types. Continuously varying states are also cut into pieces; clusters are an analysis tool, not a biological finding.
- Clustering on UMAP coordinates. Cluster on the graph in PC space; UMAP is only a display.
- Tuning resolution until the result looks right. The reason for a resolution should be clear before you see the result.
- Testing differences between clusters as independent evidence. The clusters were carved from the same data, so differences between them are significant by construction (chapter 11).
- Ignoring randomness. Another algorithm or random seed moves boundary cells between clusters; report the algorithm, number of PCs, k and resolution.