内容

1简介

咆哮包提供了一些用于定量检查集群输出的诊断。我们将在另一个数据集上演示这些诊断scRNAseq包,使用基于图形的方法通过clusterRows ()在前面的小插图中描述的通用。

library(scRNAseq) sce <- grun胰脏数据()#质量控制删除坏细胞。library(sctle) qcstats <- perCellQCMetrics(sce) qcfilter <- quickPerCellQC(qcstats, sub.fields="altexps_ERCC_percent") sce <- sce[,!#库大小的归一化。sce <- logNormCounts(sce) #特征选择。library(scran) dec <- modelGeneVar(sce) hvgs <- getTopHVGs(dec, n=1000) #降维。set.seed(1000) library(sater) sce <- runPCA(sce, ncomponents=20, subset_row=hvgs) #集群。library(bluster) mat <- reducedDim(sce) cluster .info <- clusterRows(mat, NNGraphParam(), full=TRUE) clusters <- cluster .info$clusters
##集群## 12 3 4 5 6 7 8 9 10 11 12 ## 285 171 161 59 174 49 70 137 69 65 28 23

2计算轮廓宽度

轮廓宽度是一个标准度量,用于量化由任何程序生成的集群之间的分离。与来自不同簇的细胞相比,具有较大正宽度的细胞更接近来自同一簇的其他细胞。另一方面,低宽度或负宽度表明来自不同簇的细胞没有很好地分离。

精确的轮廓计算是相当密集的计算咆哮而是实现一个近似。的approxSilhouette ()函数,该函数返回每个单元格及其最近的(非自)簇的宽度。由较低宽度的细胞组成的群集在解释时可能需要更多的注意。

sil <- approxSilhouette(mat, clusters
##数据帧与1291行和3列##集群其他宽度## <因子> <因子> <数字> ## D2ex_1 1 7 0.375510 ## D2ex_2 1 7 0.370596 ## D2ex_3 1 7 0.409271 ## D2ex_4 5 3 0.257069 ## D2ex_5 3 0.249884 ## ... ... ... ...## d17tgfb_91 6 2 0.403107 ## d17tgfb_93 17 0.384364 ## d17tgfb_94 6 2 0.243933 ## d17tgfb_95 6 2 0.204860
箱线图(分裂(sil美元宽度、集群))

该函数还返回每个单元格最接近的“其他”集群的标识。这有助于根据一个集群的单元中有多少更接近另一个集群,来确定哪些集群容易相互混淆。

最好的select <- ifelse(sil$width > 0,群集,sil$other)表(已分配=群集,最近=best.choice)
# #最近# #分配1 2 3 4 5 6 7 8 9 10 11 12 # # 1 275 0 7 0 3 0 0 0 0 0 0 0 # # 2 0 171 0 0 0 0 0 0 0 0 0 0 11 # # 3 0 0 150 0 0 0 0 0 0 0 0 # # 4 0 0 0 59 0 0 0 0 0 0 0 0 # 21 # 5 0 0 0 153 0 0 0 0 0 0 0 # 23 26 # 6 0 0 0 0 0 0 0 0 0 0 # # 7 14 0 8 10 2 0 18 0 7 2 8 1 # # 136 0 0 0 1 0 0 0 0 0 0 0 # # 9 0 0 0 0 0 0 0 10 58 0 0 1 # # 10 0 0 0 0 0 0 0 0 0 0 0 # 65 # 11 0 0 0 0 0 0 0 0 0 0 0 # # 28日12 0 0 0 0 0 0 0 0 0 0 0 23

3.计算邻域纯度

另一种诊断使用属于同一集群的每个单元的邻居百分比。分离良好的簇应表现出较高的百分比(即“纯度”),因为来自不同簇的细胞不会混合。低纯度是聚类过度的症状,其中聚类边界变得更加模糊。

neighborPurity ()函数计算每个单元格的邻域纯度。系统纯度低的聚类可能需要在解释时更加小心。默认情况下,我们执行一些加权,这样大型集群就不会有很大的纯度,因为数据集中分配给其他集群的单元格很少。

pure <- neighborPurity(席子,集群)纯
##数据帧与1291行和2列##纯度最大## <数值> <因子> ## D2ex_1 1.000000 1 ## D2ex_2 1.000000 1 ## D2ex_3 1.000000 1 ## D2ex_4 0.951603 5 ## D2ex_5 1.000000 5 ## ... ... ...1 ## d17tgfb_94 1.000000 1 ## d17tgfb_94 0.986538 6 ## d17tgfb_95 0.898817 6
箱线图(分裂(纯纯洁美元,集群))

该函数还返回百分比最高的另一个集群的标识。这对于根据哪些对在它们的邻域中有最大的混合来确定集群之间的关系是有用的。

分配表(=集群,Max =纯美元最大)
# #马克斯# #分配1 2 3 4 5 6 7 8 9 10 11 12 # # 1 279 0 0 0 0 0 6 0 0 0 0 0 # # 2 0 170 0 0 0 0 0 0 0 0 0 1 # # 3 0 0 158 0 3 0 0 0 0 0 0 0 # # 4 0 0 0 0 0 0 0 0 0 0 0 # 59 # 165 5 1 0 6 0 0 2 0 0 0 0 0 # # 6 31 0 18 0 0 0 0 0 0 0 0 0 # # 67 0 0 0 1 0 0 0 1 0 1 0 # # 136 0 0 0 0 0 0 0 1 0 0 0 # # 9 0 0 0 0 0 0 0 5 64 0 0 0 # # 10 0 0 0 0 0 0 0 0 0 65 0 0 # # 11 0 0 0 0 0 0 0 0 0 0 0 # # 28日12 0 0 0 0 0 0 0 0 0 0 0 23

4计算每个集群的RMSD

每个簇的均方根偏差(RMSD)表示每个簇内细胞的分散情况。较大的RMSD值表明集群具有较高的内部异质性,使其成为进一步进行子集群的良好候选者。

rmsd <- clusterRMSD(mat, clusters) barplot(rmsd)

或者,我们可以计算集群内平方和(WCSS),这是在\ (k \)——集群。人们可以选择一个“明智的”选择\ (k \)通过计算WCSS的值范围和选择的值,WCSS开始高原-见节8欲知详情。

clusterRMSD(mat, clusters, sum=TRUE)
## 12 3 4 56 7 8 ## 60368.807 9537.386 26566.192 19009.470 30701.291 8244.528 31829.154 14682.105 ## 9 10 11 12 ## 10652.129 6094.776 2644.849 1956.404

5计算图的模块化

对于基于图的方法,我们可以计算聚类内部和成对聚类之间的聚类模块化。具体来说,我们检查了每对聚类的观察到的和期望的边权的比率(与许多聚类中使用的模块化评分密切相关)cluster_ *函数从igraph).我们通常期望看到同一簇中细胞之间的高权重,而簇之间的最小权重,这表明簇是分离良好的。较大的非对角线条目表明对应的簇对密切相关。

g <- cluster .info$objects$graph ratio <- pairwiseModularity(g, clusters, as.ratio=TRUE) library(pheatmap) pheatmap(log10(ratio+1), cluster_cols=FALSE, cluster_rows=FALSE, col=rev(heat.colors(100)))

使用力导向布局可能会更好地可视化:

集群。gr <- igraph::graph_from_adjacency_matrix(log2(ratio+1), mode="upper", weighted=TRUE, diag=FALSE) #增加权重以增加线条的可见性。set.seed(1100101)情节(集群。gr, edge.width=igraph::E(cluster.gr)$weight*5, layout=igraph::layout_with_lgl)

我们还可以调整聚类的分辨率事后mergeCommunities ()函数。这将迭代地将最密切相关的集群对合并在一起,直到达到所需的集群数量。例如,如果我们想将集群的数量减少到10个,我们可以这样做:

merge <- mergecommements (g, clusters, number=10) table(merged)
## 23 5 6 7 9 10 11 12 ## 285 171 161 174 49 129 206 65 28 23

6比较两个聚类

要比较两个聚类,请使用pairwiseRand ()函数计算调整的兰德指数(ARI)。ARI值高表明这两个聚类在划分观测值方面是相似的,ARI值为1意味着聚类是相同的。

hclusters <- clusterRows(mat, HclustParam(cut.dynamic=TRUE)) pairwiseRand(clusters, hclusters, mode="index")
## [1] 0.4512108

当然,单个数字并不是特别有用,所以clusterRand ()还提供了将ARI分解为来自每个集群或集群对的组件的功能。具体来说,对于“参考”集群中的每个集群或集群对(在这里,集群),我们可以看到它是否在“替代”聚类中被保留(这里,hclusters).对角线上的大值表示参考聚类被概括;对角线外的大值表示相应簇对之间的分离也保持不变。相反,低对角线值表明对应的簇在替代方案中是碎片化的,低非对角线值可用于诊断分离丢失。

ratio <- pairwiseRand(clusters, hclusters, mode="ratio") library(pheatmap) pheatmap(ratio, cluster_cols=FALSE, cluster_rows=FALSE, col=viridis::viridis(100), breaks=seq(- 1,1, length=101))

两个集群之间的显式映射可以使用linkClusters ()(见部分9).或者,我们可以用。来量化一个集群在另一个集群中的“嵌套”程度nestedClusters ();这对于验证高分辨率聚类确实嵌套在较粗的对应对象中非常有用。

7引导集群稳定性

我们可以使用自举来评估采样噪声对聚类过程稳定性的影响。的bootstrapStability ()函数将返回原始集群的ARI与自举复制生成的ARI的比较,在多个自举迭代中求平均值。高值表明聚类对采样噪声具有鲁棒性。

set.seed(1001010) ari <-bootstrapStability(mat, clusters=clusters, mode="index",腮帮am =NNGraphParam()) ari . set.seed(1001010) ari <-bootstrapStability(mat, clusters=clusters, mode="index",腮帮am =NNGraphParam()
## [1] 0.7147913

高级用户也可以设置模式= "比"为了获得噪声对每个簇(对)的影响的更详细的分解。

set.seed(1001010) ratio <-bootstrapStability(mat, clusters=clusters, mode="ratio", param =NNGraphParam()) library(pheatmap) pheatmap(ratio, cluster_cols=FALSE, cluster_rows=FALSE, col=viridis::viridis(100), breaks=seq(- 1,1, length=101))

8聚类参数扫描

clusterSweep ()函数提供了一种方便的方法来测试参数设置的多个组合。给定一个BlusterParam对象和每个参数的一组值,则该函数将对每个参数组合重复聚类。下面的示例使用基于图的聚类和各种k以及不同的团体检测算法。

组合<- clusterSweep(mat, blush param =SNNGraphParam(), k=c(5L, 10L, 15L, 20L),集群。Fun =c("walktrap", "louvain", "infomap"))

这将生成一个包含所有聚类和用于生成聚类的相应参数组合的列表。该函数将尝试为每个组合生成一些合理的名称,尽管这可能需要对大量参数进行手动管理。

colnames(组合集群美元)
“k.5_cluster.fun.”walktrap”“k.10_cluster.fun。“##[3]”k.15_cluster.fun。walktrap”“k.20_cluster.fun。“##[5]”k.5_cluster.fun。鲁汶”“k.10_cluster.fun。鲁文" ## [7]"k.15_cluster.fun。鲁汶”“k.20_cluster.fun。卢文“##[9]”k.5_cluster.fun.infomap“k.10_cluster.fun.infomap”##[11]“k.15_cluster.fun.infomap”“k.20_cluster.fun.infomap”
美元的参数组合
##数据框架12行2列## k集群。Fun ## <整数> <字符> ## k.5_cluster.fun。Walktrap ## k.10_cluster.fun。10 . Walktrap ## k.15_cluster.fun。## k.20_cluster.fun。## k.5_cluster.fun。鲁汶5鲁汶## ... ... ...# # k.20_cluster.fun。鲁汶20鲁汶## k.5_cluster.fun.infomap 5 infomap ## k.10_cluster.fun.infomap 10 infomap ## k.15_cluster.fun.infomap 15 infomap ## k.20_cluster.fun.infomap 20 infomap

我们可以将其与上面定义的一些指标结合起来,将聚类分离量化为聚类参数的函数。这使我们能够快速确定哪些参数对结果有显著影响。原则上,我们可以选择分离度最大的聚类进行进一步分析;然而,这往往是令人失望的,因为它往往倾向于过于宽泛的集群。

set.seed(10) nclusters <- 3:25 kcombos <- clusterSweep(mat, param =KmeansParam(centers=5), centers=nclusters) sil <- vapply(as.list(kcombos$clusters), function(x) mean(approxSilhouette(mat, x)$width), 0) plot(nclusters, sil, xlab="群集数量",ylab="平均轮廓宽度")

pur <- vapply(as.list(kcombos$clusters), function(x) mean(neighborPurity(mat, x)$purity), 0) plot(nclusters, pur, xlab="群集数量",ylab="平均纯度")

wcss <- vapply(as.list(kcombos$clusters), function(x) sum(clusterRMSD(mat, x, sum=TRUE)), 0) plot(nclusters, wcss, xlab="集群数量",ylab="集群内平方和")

9连接集群

如果我们有很多聚类,我们可以用linkClusters ()函数。这构造了一个图,其中边缘在来自不同聚类的聚类对之间形成,基于分配给两个聚类的细胞数量。重新使用之前扫描的一些聚类,我们可以这样做:

link <- linkClusters(list(walktrap=combination $clusters$k.10_cluster.fun. list)集群k.10_cluster.fun美元walktrap鲁汶=组合。Louvain, infomap=combination $clusters$k.10_cluster.fun.infomap)链接
## IGRAPH 4a9ee83 UNW- 44 78—## + attr: name (v/c), weight (e/n) ## + edges from 4a9ee83(顶点名称):## [1]walktrap。1——鲁汶。1 walktrap。3.--louvain.1 walktrap.7 --louvain.1 ## [4] walktrap.3 --louvain.2 walktrap.5 --louvain.2 walktrap.3 --louvain.3 ## [7] walktrap.7 --louvain.3 walktrap.11--louvain.3 walktrap.3 --louvain.4 ## [10] walktrap.5 --louvain.4 walktrap.4 --louvain.5 walktrap.7 --louvain.5 ## [13] walktrap.6 --louvain.6 walktrap.8 --louvain.6 walktrap.10--louvain.7 ## [16] walktrap.2 --louvain.8 walktrap.6 --louvain.8 walktrap.8 --louvain.9 ## [19] walktrap.9 --louvain.9 walktrap.12--louvain.10 walktrap.1 --infomap.1 ## [22] louvain.1 --infomap.1 walktrap.1 --infomap.2 walktrap.7 --infomap.2 ## + ... omitted several edges

这可以用来可视化集群之间的关系,或者通过社区检测算法来跨集群识别元集群:

Meta <- igraph::cluster_walktrap(linked) plot(linked, mark.groups= Meta)

默认情况下,边缘权重是通过将共享单元数与两个集群中单元总数中较小的单元数相除来计算的。这有利于一个聚类中的大聚类和另一个(更好的)聚类中的小子聚类之间的强边缘。替代加权方案将倾向于在聚类之间进行1:1的映射,这更容易解释。

10比较多个聚类

compareClusterings ()函数将返回不同聚类对之间的ARIs的对称矩阵。这有助于可视化不同聚类之间的关系,例如,查看哪些参数最有助于聚类之间的差异。

aris <- compareClusterings(combination $clusters) g <- igraph::graph。adjacency(aris, mode="undirected", weighted=TRUE) meta2 <- igraph::cluster_walktrap(g) plot(g, mark.groups=meta2)

我们还可以识别聚类组,通常对应于产生或多或少相似结果的参数组合。这使我们能够在下游分析之前剔除大量冗余的组合。

会话信息

sessionInfo ()
## R版本4.2.1(2022-06-23)##平台:x86_64-pc-linux-gnu(64位)##运行在Ubuntu 20.04.5 LTS ## ##矩阵产品:默认## BLAS: /home/biocbuild/bbs-3.16-bioc/R/lib/libRblas。/home/biocbuild/bbs-3.16-bioc/R/lib/libRlapack。所以## ## locale: ## [1] LC_CTYPE=en_US。UTF-8 LC_NUMERIC= c# # [3] LC_TIME=en_GB LC_COLLATE= c# # [5] LC_MONETARY=en_US。utf - 8 LC_MESSAGES = en_US。UTF-8 ## [7] LC_PAPER=en_US。UTF-8 LC_NAME= c# # [9] LC_ADDRESS=C lc_phone = c# # [11] LC_MEASUREMENT=en_US。UTF-8 LC_IDENTIFICATION=C ## ##附加的基本包:## [1]stats4 stats graphics grDevices utils datasets methods ##[8]基础## ##其他附加包:## [7] scRNAseq_2.11.0 SingleCellExperiment_1.20.0 ## [9] SummarizedExperiment_1.28.0 Biobase_2.58.0 ## [13] IRanges_2.32.0 S4Vectors_0.36.0 ## [15] BiocGenerics_0.44.0 MatrixGenerics_1.10.0 ## [17] matrixStats_0.62.0 BiocStyle_2.26.0 ## ##通过命名空间加载(并且没有附加):[1] AnnotationHub_3.6.0 BiocFileCache_2.6.0 ## [5] gmp_0.6-7 biocparallel_32.0 ## [7] benchmarkme_1.0.8 digest_0.6.30 ## [11] htmltools_0.5.3 magick_2.7.3 ## [13] viridis_0.6.2 fansi_1.0.3 ## [15] magrittr_2.0.3 memoise_2.0.1 ## [17] mbkmeans_1.14.0 ScaledMatrix_1.6.0 ## [19] doParallel_1.0.17 cluster_2.1.4 ## [21] limma_3.54.0 Biostrings_2.66.0 ## [23] prettyunits_1.1.1 colorspace_2.0-3 ## [25] ggrepel_0.9.1blob_1.2.3 # # [27] rappdirs_0.3.3 xfun_0.34 # # [29] dplyr_1.0.10 kohonen_3.0.11 # # [31] crayon_1.5.2 rcurl_1.98 - 1.9 # # [33] jsonlite_1.8.3 iterators_1.0.14 # # [35] glue_1.6.2 gtable_0.3.1 # # [37] zlibbioc_1.44.0 XVector_0.38.0 # # [39] DelayedArray_0.24.0 BiocSingular_1.14.0 # # [41] apcluster_1.4.10 scales_1.2.1 # # [43] DBI_1.1.3 edgeR_3.40.0 # # [45] Rcpp_1.0.9 viridisLite_0.4.1 # # [47] xtable_1.8-4 progress_1.2.2 # # [49] dqrng_0.3.0 bit_4.0.4 # # [51] rsvd_1.0.5 metapod_1.6.0 # # [53] httr_1.4.4RColorBrewer_1.1-3 # # [55] FNN_1.1.3.1 ellipsis_0.3.2 # # [57] ClusterR_1.2.7 farver_2.1.1 # # [59] pkgconfig_2.0.3 xml_3.99 - 0.12 # # [61] uwot_0.1.14 sass_0.4.2 # # [63] dbplyr_2.2.1 dynamicTreeCut_1.63-1 # # [65] locfit_1.5 - 9.6 utf8_1.2.2 # # [67] labeling_0.4.2 tidyselect_1.2.0 # # [69] rlang_1.0.6 later_1.3.0 # # [71] AnnotationDbi_1.60.0 munsell_0.5.0 # # [73] BiocVersion_3.16.0 tools_4.2.1 # # [75] cachem_1.0.6 cli_3.4.1 # # [77] generics_0.1.3 RSQLite_2.2.18 # # [79] ExperimentHub_2.6.0 evaluate_0.17## [81] stringr_1.4.1 fastmap_1.1.0 ## [83] yaml_2.3.6 knitr_1.40 ## [85] bit64_4.0.5 purrr_0.3.5 ## [87] KEGGREST_1.38.0 AnnotationFilter_1.22.0 ## [89] sparseMatrixStats_1.10.0 mime_0.12 ## [91] xml2_1.3.3 biomaRt_2.54.0 ## [93] compiler_4.2.1 beeswarm_0.4.0 ## [95] filelock_1.0.2 curl_4.3.3 ## [97] png_0.1-7 interactiveDisplayBase_1.36.0 ## [99] tibble_3.1.8 statmod_1.4.37 ## [101] bslib_0.4.0 stringi_1.7.8 ## [103] highr_0.9 GenomicFeatures_1.50.0 ## [105] lattice_0.20-45 ProtGenerics_1.30.0 ## [107] Matrix_1.5-1 vctrs_0.5.0 ## [109] pillar_1.8.1 lifecycle_1.0.3 ## [111] BiocManager_1.30.19 jquerylib_0.1.4 ## [113] BiocNeighbors_1.16.0 cowplot_1.1.1 ## [115] bitops_1.0-7 irlba_2.3.5.1 ## [117] httpuv_1.6.6 rtracklayer_1.58.0 ## [119] R6_2.5.1 BiocIO_1.8.0 ## [121] bookdown_0.29 promises_1.2.0.1 ## [123] gridExtra_2.3 vipor_0.4.5 ## [125] codetools_0.2-18 benchmarkmeData_1.0.4 ## [127] gtools_3.9.3 assertthat_0.2.1 ## [129] rjson_0.2.21 withr_2.5.0 ## [131] GenomicAlignments_1.34.0 Rsamtools_2.14.0 ## [133] GenomeInfoDbData_1.2.9 parallel_4.2.1 ## [135] hms_1.1.2 grid_4.2.1 ## [137] beachmat_2.14.0 rmarkdown_2.17 ## [139] DelayedMatrixStats_1.20.0 shiny_1.7.3 ## [141] ggbeeswarm_0.6.0 restfulr_0.0.15