比较不同的对单细胞转录组数据聚类的方法

背景介绍

聚类之前必须要对表达矩阵进行normalization,而且要去除一些批次效应等外部因素。通过对表达矩阵的聚类,可以把细胞群体分成不同的状态,解释为什么会有不同的群体。不过从计算的角度来说,聚类还是蛮复杂的,各个细胞并没有预先标记好,而且也没办法事先知道可以聚多少类。尤其是在单细胞转录组数据里面有很高的噪音,基因非常多,意味着的维度很高。

对这样的高维数据,需要首先进行降维,可以选择PCA或者t-SNE方法。聚类的话,一般都是无监督聚类方法,比如:hierarchical clustering, k-means clustering and graph-based clustering。算法略微有一点复杂,略过吧。

这里主要比较6个常见的单细胞转录组数据的聚类包:

  • SINCERA

  • pcaReduce

  • SC3

  • tSNE + k-means

  • SEURAT

  • SNN-Cliq

所以需要安装并且加载一些包,安装代码如下;

install.packages('pcaReduce')
## try http:// if https:// URLs are not supported
source("https://bioconductor.org/biocLite.R")
biocLite("SC3")
biocLite("Seurat")
install.packages("devtools")
library("devtools")
install_github("BPSC","nghiavtr")
install_github("hemberg-lab/scRNA.seq.funcs")
devtools::install_github("JustinaZ/pcaReduce")

加载代码如下:

library(pcaMethods)
library(pcaReduce)
library(SC3)
library(scater)
library(pheatmap)
set.seed(1234567)

加载测试数据

这里选取的是数据,加载了这个scater包的SCESet对象,包含着一个23730 features, 301 samples 的表达矩阵。

供11已知的种细胞类型,这样聚类的时候就可以跟这个已知信息做对比,看看聚类效果如何。

可以直接用plotPCA来简单PCA并且可视化。

pollen <- readRDS("../pollen/pollen.rds")
pollen
## SCESet (storageMode: lockedEnvironment)
## assayData: 23730 features, 301 samples
##   element names: exprs, is_exprs, tpm
## protocolData: none
## phenoData
##   rowNames: Hi_2338_1 Hi_2338_2 ... Hi_GW16_26 (301 total)
##   varLabels: cell_type1 cell_type2 ... is_cell_control (33 total)
##   varMetadata: labelDescription
## featureData
##   featureNames: A1BG A1BG-AS1 ... ZZZ3 (23730 total)
##   fvarLabels: mean_exprs exprs_rank ... feature_symbol (11 total)
##   fvarMetadata: labelDescription
## experimentData: use 'experimentData(object)'
## Annotation:
head(fData(pollen))
##          mean_exprs exprs_rank n_cells_exprs total_feature_exprs
## A1BG     0.56418762      12460            79           169.82048
## A1BG-AS1 0.31265010      10621            37            94.10768
## A1CF     0.05453986       6796            59            16.41650
## A2LD1    0.22572953       9781            28            67.94459
## A2M      0.15087563       8855            21            45.41356
## A2M-AS1  0.02428046       5366             3             7.30842
##          pct_total_exprs pct_dropout total_feature_tpm
## A1BG        1.841606e-03    73.75415            481.37
## A1BG-AS1    1.020544e-03    87.70764            538.18
## A1CF        1.780276e-04    80.39867             13.99
## A2LD1       7.368203e-04    90.69767            350.65
## A2M         4.924842e-04    93.02326           1356.63
## A2M-AS1     7.925564e-05    99.00332             88.61
##          log10_total_feature_tpm pct_total_tpm is_feature_control
## A1BG                    2.683380  1.599256e-04              FALSE
## A1BG-AS1                2.731734  1.787996e-04              FALSE
## A1CF                    1.175802  4.647900e-06              FALSE
## A2LD1                   2.546111  1.164965e-04              FALSE
## A2M                     3.132781  4.507134e-04              FALSE
## A2M-AS1                 1.952356  2.943891e-05              FALSE
##          feature_symbol
## A1BG               A1BG
## A1BG-AS1       A1BG-AS1
## A1CF               A1CF
## A2LD1             A2LD1
## A2M                 A2M
## A2M-AS1         A2M-AS1
table(pData(pollen)$cell_type1)
##
##   2338   2339     BJ   GW16   GW21 GW21+3  hiPSC   HL60   K562   Kera
##     22     17     37     26      7     17     24     54     42     40
##    NPC
##     15
plotPCA(pollen, colour_by = "cell_type1")

可以看到简单的PCA也是可以区分部分细胞类型的,只不过在某些细胞相似性很高的群体区分力度不够,所以需要开发新的算法来解决这个聚类的问题。

SC聚类

pollen <- sc3_prepare(pollen, ks = 2:5)
pollen <- sc3_estimate_k(pollen)
pollen@sc3$k_estimation
## [1] 11
## 准备 SCESet对象 数据给 SC3方法,先预测能聚多少个类,发现恰好是11个。

## 这里是并行计算,所以速度还可以
pollen <- sc3(pollen, ks = 11, biology = TRUE)
pollen
## SCESet (storageMode: lockedEnvironment)
## assayData: 23730 features, 301 samples
##   element names: exprs, is_exprs, tpm
## protocolData: none
## phenoData
##   rowNames: Hi_2338_1 Hi_2338_2 ... Hi_GW16_26 (301 total)
##   varLabels: cell_type1 cell_type2 ... sc3_11_log2_outlier_score
##     (35 total)
##   varMetadata: labelDescription
## featureData
##   featureNames: A1BG A1BG-AS1 ... ZZZ3 (23730 total)
##   fvarLabels: mean_exprs exprs_rank ... sc3_11_de_padj (16 total)
##   fvarMetadata: labelDescription
## experimentData: use 'experimentData(object)'
## Annotation:
head(fData(pollen))
##          mean_exprs exprs_rank n_cells_exprs total_feature_exprs
## A1BG     0.56418762      12460            79           169.82048
## A1BG-AS1 0.31265010      10621            37            94.10768
## A1CF     0.05453986       6796            59            16.41650
## A2LD1    0.22572953       9781            28            67.94459
## A2M      0.15087563       8855            21            45.41356
## A2M-AS1  0.02428046       5366             3             7.30842
##          pct_total_exprs pct_dropout total_feature_tpm
## A1BG        1.841606e-03    73.75415            481.37
## A1BG-AS1    1.020544e-03    87.70764            538.18
## A1CF        1.780276e-04    80.39867             13.99
## A2LD1       7.368203e-04    90.69767            350.65
## A2M         4.924842e-04    93.02326           1356.63
## A2M-AS1     7.925564e-05    99.00332             88.61
##          log10_total_feature_tpm pct_total_tpm is_feature_control
## A1BG                    2.683380  1.599256e-04              FALSE
## A1BG-AS1                2.731734  1.787996e-04              FALSE
## A1CF                    1.175802  4.647900e-06              FALSE
## A2LD1                   2.546111  1.164965e-04              FALSE
## A2M                     3.132781  4.507134e-04              FALSE
## A2M-AS1                 1.952356  2.943891e-05              FALSE
##          feature_symbol sc3_gene_filter sc3_11_markers_clusts
## A1BG               A1BG            TRUE                     5
## A1BG-AS1       A1BG-AS1            TRUE                     4
## A1CF               A1CF            TRUE                     2
## A2LD1             A2LD1           FALSE                    NA
## A2M                 A2M           FALSE                    NA
## A2M-AS1         A2M-AS1           FALSE                    NA
##          sc3_11_markers_padj sc3_11_markers_auroc sc3_11_de_padj
## A1BG            7.740802e-10            0.8554452   1.648352e-18
## A1BG-AS1        1.120284e-03            0.6507985   5.575777e-03
## A1CF            5.007946e-23            0.8592113   1.162843e-17
## A2LD1                     NA                   NA             NA
## A2M                       NA                   NA             NA
## A2M-AS1                   NA                   NA             NA
## 可以看到SC3方法处理后的SCESet对象的基因信息增加了5列,比较重要的是sc3_gene_filter信息,决定着该基因是否拿去聚类,因为基因太多了,需要挑选
table(fData(pollen)$sc3_gene_filter)
##
## FALSE  TRUE
## 11902 11828
### 只有一半的基因被挑选去聚类了

## 后面是一些可视化
sc3_plot_consensus(pollen, k = 11, show_pdata = "cell_type1")

sc3_plot_silhouette(pollen, k = 11)

sc3_plot_expression(pollen, k = 11, show_pdata = "cell_type1")

sc3_plot_markers(pollen, k = 11, show_pdata = "cell_type1")

plotPCA(pollen, colour_by = "sc3_11_clusters")

## 还支持shiny的交互式聚类,暂时不显示
# sc3_interactive(pollen)

很明显可以看到SC3聚类的效果要好于普通的PCA

pcaReduce

# use the same gene filter as in SC3
input <- exprs(pollen[fData(pollen)$sc3_gene_filter, ])
# run pcaReduce 1 time creating hierarchies from 1 to 30 clusters
pca.red <- PCAreduce(t(input), nbt = 1, q = 30, method = 'S')[[1]]
##  这里对2~30种类别的情况都分别对样本进行分组。
## 我们这里取只有11组的时候,这些样本是如何分组的信息来可视化。
pData(pollen)$pcaReduce <- as.character(pca.red[,32 - 11])
plotPCA(pollen, colour_by = "pcaReduce")

tSNE + kmeans

scater包包装了 Rtsne 和 ggplot2 来做tSNE并且可视化。

pollen <- plotTSNE(pollen, rand_seed = 1, return_SCESet = TRUE)

## 上面的tSNE的结果,下面用kmeans的方法进行聚类,假定是8类细胞类型。
pData(pollen)$tSNE_kmeans <- as.character(kmeans(pollen@reducedDimension, centers = 8)$clust)
plotTSNE(pollen, rand_seed = 1, colour_by = "tSNE_kmeans")

SNN-Cliq

这个有一点难用,算了吧。

distan <- "euclidean"
par.k <- 3
par.r <- 0.7
par.m <- 0.5
# construct a graph
scRNA.seq.funcs::SNN(
   data = t(input),
   outfile = "snn-cliq.txt",
   k = par.k,
   distance = distan
)
# find clusters in the graph
snn.res <-
   system(
       paste0(
           "python snn-cliq/Cliq.py ",
           "-i snn-cliq.txt ",
           "-o res-snn-cliq.txt ",
           "-r ", par.r,
           " -m ", par.m
       ),
       intern = TRUE
   )
cat(paste(snn.res, collapse = "\n"))
snn.res <- read.table("res-snn-cliq.txt")
# remove files that were created during the analysis
system("rm snn-cliq.txt res-snn-cliq.txt")
pData(pollen)$SNNCliq <- as.character(snn.res[,1])
plotPCA(pollen, colour_by = "SNNCliq")

SINCERA

至少是在这个数据集上面表现不咋地

# perform gene-by-gene per-sample z-score transformation
dat <- apply(input, 1, function(y) scRNA.seq.funcs::z.transform.helper(y))
# hierarchical clustering
dd <- as.dist((1 - cor(t(dat), method = "pearson"))/2)
hc <- hclust(dd, method = "average")
num.singleton <- 0
kk <- 1
for (i in 2:dim(dat)[2]) {
   clusters <- cutree(hc, k = i)
   clustersizes <- as.data.frame(table(clusters))
   singleton.clusters <- which(clustersizes$Freq < 2)
   if (length(singleton.clusters) <= num.singleton) {
       kk <- i
   } else {
       break;
   }
}
cat(kk)
## 14
pheatmap(
   t(dat),
   cluster_cols = hc,
   cutree_cols = 14,
   kmeans_k = 100,
   show_rownames = FALSE
)

SEURAT

library(Seurat)
pollen_seurat <- new("seurat", raw.data = get_exprs(pollen, exprs_values = "tpm"))
pollen_seurat <- Setup(pollen_seurat, project = "Pollen")
pollen_seurat <- MeanVarPlot(pollen_seurat)
pollen_seurat <- RegressOut(pollen_seurat, latent.vars = c("nUMI"),
                           genes.regress = pollen_seurat@var.genes)
pollen_seurat <- PCAFast(pollen_seurat)
pollen_seurat <- RunTSNE(pollen_seurat)
pollen_seurat <- FindClusters(pollen_seurat)
TSNEPlot(pollen_seurat, do.label = T)
pData(pollen)$SEURAT <- as.character(pollen_seurat@ident)
sc3_plot_expression(pollen, k = 11, show_pdata = "SEURAT")
markers <- FindMarkers(pollen_seurat, 2)
FeaturePlot(pollen_seurat,
           head(rownames(markers)),
           cols.use = c("lightgrey", "blue"),
           nCol = 3)

(0)

相关推荐

  • Seurat学习与使用(一)

    简介Seurat是一个r包,被设计用于单细胞rna-seq数据的细胞质控和分析.Seurat旨在使用户能够识别和解释单细胞转录组数据中的异质性来源,同时提供整合不同类型的单细胞数据的函数.目前Seur ...

  • 单细胞转录组揭示乳腺癌转移能量代谢改变

    image-20200331112435323.png 背景简介 本文题为:Transcriptional diversity and bioenergetic shift in human brea ...

  • 比较不同单细胞转录组数据寻找features方法

    挑选到的跟feature相关的基因集,有点类似于在某些组间差异表达的基因集,都需要后续功能注释. 背景介绍 单细胞转录组测序的确可以一次性对所有细胞都检测到上千个基因的表达,但是,大多数情况下,只有其 ...

  • 科研 | NC:使用iDEA方法对单细胞转录组数据进行差异表达和基因富集分析

    编译:夕夕,编辑:十九.江舜尧. 原创微文,欢迎转发转载. 导读 差异表达分析(DE)和基因富集分析(GSE)常用于单细胞转录组研究中.本研究中,作者开发了一种集成且可扩展的方法--iDEA,可通过分 ...

  • 用Expedition来分析单细胞转录组数据的可变剪切

    了解我的应该都知道我最近几个月都在奋战一个陌生的领域,单细胞转录组数据处理.真的很有挑战性,笔记累积了一大堆了,但是没有太值得分享的,大多是利用bulk转录组数据处理的经验而已,但是下面这个是单细胞转 ...

  • 比较不同的对单细胞转录组数据normalization方法

    使用CPM去除文库大小影响 之所以需要normalization,就是因为测序的各个细胞样品的总量不一样,所以测序数据量不一样,就是文库大小不同,这个因素是肯定需要去除.最简单的就是counts pe ...

  • 比较不同的对单细胞转录组数据寻找差异基因的方法

    背景介绍 如果是bulk RNA-seq,那么现在最流行的就是DESeq2 和 edgeR啦,而且有很多经过了RT-qPCR 验证过的真实测序数据可以来评价不同的差异基因算法的表现. 对单细胞测序数据 ...

  • 10个单细胞转录组数据探索免疫治疗机理(逆向收费读文献2019-12)

    栏目起源 逆向收费读文献社群(2018-01-07) 逆向收费读文献社群 (2018-06-09) 逆向收费读文献社群(第二年通知)(2019-01-26) 大概有50人加入吧,成功坚持下来的朋友们累 ...

  • 单细胞转录组数据的个性化分析汇总

    都介绍到单细胞转录组数据处理之细胞亚群比例比较部分了,10讲就告一段落了,大家可以回看仔细品读.后面的分析其实都是个性化的了,取决于课题设计,假说,生物学背景知识,而且需要学习大量的R包. 既然是个性 ...

  • 都已经开始挖掘空间单细胞转录组数据了

    最近各个公众号都在鼓吹单细胞转录组数据套路,感觉这样的科研风气不好,数据挖掘这个技能最大的作用应该是避免大家重复浪费科研经费去做一些明明可以通过分析公共数据库拿到的结论! 比如你研究的癌症里面哪些基因 ...

  • 10X单细胞转录组数据的动态阈值过滤

    总是有粉丝在我们的各个公众号教程下面留言关于单细胞数据处理的细节问题,比如为什么我们过滤线粒体基因表达量超15%的细胞啊,为什么看核糖体基因表达量占比啊等等. 其实看一下基础10讲: 01. 上游分析 ...