<p>I've done sub-clustering a few times on my Seurat data sets. The approach I take is to subset the clusters that need to be clustered (i.e. using <code>subset</code>), carry out a clustering of only those cells, then transfer the subcluster labels back to the original dataset. Here's some rough code, which will need to be modified for your specific situation and code preferences:</p>
<pre class="lang-r prettyprint-override"><code>data.sc[[&quot;main.cluster&quot;]] &lt;- Idents(data.sc);
clusterToSubset &lt;- &quot;B cells&quot;;
data.sub &lt;- subset(data.sc, subset = main.cluster == clusterToSubset);
## ** [Cluster data.sub] **
Idents(data.sc) &lt;- &quot;main.cluster&quot;;
## This should work as long as cell order (i.e. column names) isn't changed
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub)) &lt;- 
    paste0(&quot;Sub_&quot;, Idents(data.sub));
data.sc[[&quot;merged.cluster&quot;]] &lt;- Idents(data.sc);
</code></pre>
<p>This approach will work with multiple sub-clusters as well by changing the label that is pasted onto the sub-cluster idents:</p>
<pre class="lang-r prettyprint-override"><code>data.sc[[&quot;main.cluster&quot;]] &lt;- Idents(data.sc);
clusterToSubset1 &lt;- &quot;B cells&quot;;
data.sub.1 &lt;- subset(data.sc, subset = main.cluster == clusterToSubset1);
## ** [Cluster data.sub.1] **
clusterToSubset2 &lt;- &quot;T cells&quot;;
data.sub.2 &lt;- subset(data.sc, subset = main.cluster == clusterToSubset2);
## ** [Cluster data.sub.2] **
Idents(data.sc) &lt;- &quot;main.cluster&quot;;
## This should work as long as cell order (i.e. column names) isn't changed
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.1)) &lt;- 
    paste0(&quot;Sub1_&quot;, Idents(data.sub.1));
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.2)) &lt;- 
    paste0(&quot;Sub2_&quot;, Idents(data.sub.2));
data.sc[[&quot;merged.cluster&quot;]] &lt;- Idents(data.sc);
</code></pre>

CC BY-SA 4.0
2022-01-09T20:20:14.167Z
2023-10-10T15:00:48.447Z
2023-10-10T15:00:48.447Z
gringer
<p>Increase the clustering <code>resolution</code> parameter to generate more (smaller) clusters, see <a href="https://satijalab.org/seurat/reference/findclusters" rel="nofollow noreferrer">FindClusters in the Seurat docs</a>. Whether or not this will neatly, split your clusters into subclusters depends on your data, but normally one can easily separate CD4 and NK cells from PBMCs. See also the <a href="https://lazappi.github.io/clustree/index.html" rel="nofollow noreferrer">Clustree</a> approach for determining the optimal resolution.</p>
<p>Alternatively/additionally use a cell type annotation approach that does not require clustering, e.g. Seurat V4 permits <a href="https://satijalab.org/seurat/articles/multimodal_reference_mapping.html" rel="nofollow noreferrer">reference mapping</a> and there are many other methods too</p>

CC BY-SA 4.0
2022-01-09T13:11:35.483Z
2022-01-09T13:11:35.483Z
Chris_Rands
<p><code>Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.1))</code> gives the same output as <code>Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.2))</code>.</p>
<p>Both are returning the cellIDs of all cells.</p>
<p>The correct code to generate a list of colnames of data.sc is as follows:</p>
<pre class="lang-r prettyprint-override"><code>Idents(data.sc, cells=colnames(data.sc)[colnames(data.sc) %in% colnames(data.sub.1)]) &lt;- paste0(&quot;sub1_&quot;, Idents(data.sub.1))
</code></pre>
<p>However, you can directly add the new cluster names to a metadata column in the Seurat object using the following code:</p>
<pre class="lang-r prettyprint-override"><code>## Set up new metadata column to store subcluster IDs later ##
data.sc$subcluster &lt;- Idents(data.sc)

## subclustering steps (from a previous comment)##
data.sub.1 &lt;- subset(data.sc, subset = seurat_clusters == 1)
data.sub.1 &lt;- FindVariableFeatures(data.sub.1)
data.sub.1 &lt;- ScaleData(data.sub.1)
data.sub.1 &lt;- RunPCA(data.sub.1, verbose = FALSE)
data.sub.1 &lt;- RunUMAP(data.sub.1, reduction = &quot;pca&quot;, dims = 1:30)
data.sub.1 &lt;- FindNeighbors(data.sub.1, reduction = &quot;pca&quot;, dims = 1:30)
data.sub.1 &lt;- FindClusters(data.sub.1, resolution = 0.5)

## merging the subclusster names back to original clusters ##
data.sc<span class="math-container">$subcluster[colnames(dta.sc)[colnames(data.sc) %in% colnames(data.sub.1)]] &lt;- paste0("sub1_", data.sub.1$</span>seurat_clusters)
<span class="math-container">```</span>
</code></pre>

CC BY-SA 4.0
2023-10-10T20:50:23.503Z
If those two commands are producing the same output, it means that the subsets (i.e. `data.sub.1` and `data.sub.2`) are identical, i.e. that the subsetting did not work properly.
gringer
CC BY-SA 4.0
2023-10-10T13:03:40.663Z
2023-10-10T16:40:49.040Z
2023-10-10T16:40:49.040Z
Kenneth
<p>I've analyzed my scRNA-seq data and have a couple of Seurat clusters that show more than one cell type in each cluster. (for example, cluster 9 shows both NK and CD4 cells)
How can I split a cluster into subclusters, based on the gene expression?</p>

<scrnaseq><seurat><single-cell><gene-expression><clustering>
How to split a Seurat cluster in several subclusters?
# How to split a Seurat cluster in several subclusters?

(Asked by: username_0 on 2022-01-08)

I've analyzed my scRNA-seq data and have a couple of Seurat clusters that show more than one cell type in each cluster. (for example, cluster 9 shows both NK and CD4 cells)
How can I split a cluster into subclusters, based on the gene expression?

**Tags:** scrnaseq, seurat, single-cell, gene-expression, clustering

---

## 3 answers

### Answer by username_1 on 2022-01-09. Score: 1

I've done sub-clustering a few times on my Seurat data sets. The approach I take is to subset the clusters that need to be clustered (i.e. using subset), carry out a clustering of only those cells, then transfer the subcluster labels back to the original dataset. Here's some rough code, which will need to be modified for your specific situation and code preferences:
data.sc[["main.cluster"]] <- Idents(data.sc);
clusterToSubset <- "B cells";
data.sub <- subset(data.sc, subset = main.cluster == clusterToSubset);
## ** [Cluster data.sub] **
Idents(data.sc) <- "main.cluster";
## This should work as long as cell order (i.e. column names) isn't changed
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub)) <- 
    paste0("Sub_", Idents(data.sub));
data.sc[["merged.cluster"]] <- Idents(data.sc);

This approach will work with multiple sub-clusters as well by changing the label that is pasted onto the sub-cluster idents:
data.sc[["main.cluster"]] <- Idents(data.sc);
clusterToSubset1 <- "B cells";
data.sub.1 <- subset(data.sc, subset = main.cluster == clusterToSubset1);
## ** [Cluster data.sub.1] **
clusterToSubset2 <- "T cells";
data.sub.2 <- subset(data.sc, subset = main.cluster == clusterToSubset2);
## ** [Cluster data.sub.2] **
Idents(data.sc) <- "main.cluster";
## This should work as long as cell order (i.e. column names) isn't changed
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.1)) <- 
    paste0("Sub1_", Idents(data.sub.1));
Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.2)) <- 
    paste0("Sub2_", Idents(data.sub.2));
data.sc[["merged.cluster"]] <- Idents(data.sc);


---

### Answer by username_2 on 2022-01-09. Score: 1

Increase the clustering `resolution` parameter to generate more (smaller) clusters, see [FindClusters in the Seurat docs](https://satijalab.org/seurat/reference/findclusters). Whether or not this will neatly, split your clusters into subclusters depends on your data, but normally one can easily separate CD4 and NK cells from PBMCs. See also the [Clustree](https://lazappi.github.io/clustree/index.html) approach for determining the optimal resolution.

Alternatively/additionally use a cell type annotation approach that does not require clustering, e.g. Seurat V4 permits [reference mapping](https://satijalab.org/seurat/articles/multimodal_reference_mapping.html) and there are many other methods too


---

### Answer by username_3 on 2023-10-10. Score: 0

Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.1)) gives the same output as Idents(data.sc, cells=colnames(data.sc) %in% colnames(data.sub.2)).
Both are returning the cellIDs of all cells.
The correct code to generate a list of colnames of data.sc is as follows:
Idents(data.sc, cells=colnames(data.sc)[colnames(data.sc) %in% colnames(data.sub.1)]) <- paste0("sub1_", Idents(data.sub.1))

However, you can directly add the new cluster names to a metadata column in the Seurat object using the following code:
## Set up new metadata column to store subcluster IDs later ##
data.sc$subcluster <- Idents(data.sc)

## subclustering steps (from a previous comment)##
data.sub.1 <- subset(data.sc, subset = seurat_clusters == 1)
data.sub.1 <- FindVariableFeatures(data.sub.1)
data.sub.1 <- ScaleData(data.sub.1)
data.sub.1 <- RunPCA(data.sub.1, verbose = FALSE)
data.sub.1 <- RunUMAP(data.sub.1, reduction = "pca", dims = 1:30)
data.sub.1 <- FindNeighbors(data.sub.1, reduction = "pca", dims = 1:30)
data.sub.1 <- FindClusters(data.sub.1, resolution = 0.5)

## merging the subclusster names back to original clusters ##
data.sc$subcluster[colnames(dta.sc)[colnames(data.sc) %in% colnames(data.sub.1)]] <- paste0("sub1_", data.sub.1$seurat_clusters)
```

> **Comments:**
> **username_1**: If those two commands are producing the same output, it means that the subsets (i.e. `data.sub.1` and `data.sub.2`) are identical, i.e. that the subsetting did not work properly.  

---

