這里是佳奧!我們補充了相關(guān)知識,現(xiàn)在進一步學(xué)習(xí)相關(guān)R包的使用方法。
文章數(shù)據(jù):Low-coverage single-cell mRNA sequencing reveals cellular heterogeneity and activated signaling pathways in developing cerebral cortex
簡要的流程在Git Hub下載的壓縮包中,section02-scRNA文件夾的study_scRNAseq文件。

打開R Project文件,我們正式開始吧。
注:從這里開始,難度會明顯提高,先從運行代碼開始,再通過幫助文檔和參考代碼逐漸理解,最后理解下列代碼。這需要時間。
1 R包安裝與鏡像設(shè)置
rm(list = ls())
Sys.setenv(R_MAX_NUM_DLLS=999) ##Sys.setenv修改環(huán)境設(shè)置,R的namespace是有上限的,如果導(dǎo)入包時超過這個上次就會報錯,R_MAX_NUM_DLLS可以修改這個上限
options(stringsAsFactors = F) ##options:允許用戶對工作空間進行全局設(shè)置,stringsAsFactors防止R自動把字符串string的列辨認(rèn)成factor
options()$repos ## 查看使用install.packages安裝時的默認(rèn)鏡像
options()$BioC_mirror ##查看使用bioconductor的默認(rèn)鏡像
options(BioC_mirror="https://mirrors.ustc.edu.cn/bioc/") ##指定鏡像,這個是中國科技大學(xué)鏡像
options("repos" = c(CRAN="https://mirrors.tuna.tsinghua.edu.cn/CRAN/")) ##指定install.packages安裝鏡像,這個是清華鏡像
options()$repos
options()$BioC_mirror
# http://www.bio-info-trainee.com/3727.html 周末生物信息學(xué)培訓(xùn)班準(zhǔn)備工作
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager") ##判斷是否存在BiocManager包,不存在的話安裝
if(!require('Seurat')){
BiocManager::install('Seurat',ask = F,update = F)
}
if(!require('scran')){
BiocManager::install(c( 'scran'),ask = F,update = F)
}
if(!require('monocle')){
BiocManager::install(c( 'monocle'),ask = F,update = F)
}
## http://cole-trapnell-lab.github.io/monocle-release/monocle3/
BiocManager::install('destiny')
BiocManager::install(c( 'flexclust','mcclust'),ask = F,update = F)
BiocManager::install(c( 'scRNAseq'),ask = F,update = F)
BiocManager::install(c( 'dbscan'),ask = F,update = F)
BiocManager::install(c( 'M3Drop'),ask = F,update = F)
rm(list = ls()) # clear the environment
#load all the necessary libraries
options(warn=-1) # turn off warning message globally
suppressMessages(library(reticulate))
suppressMessages(library(devtools))
suppressMessages(library(monocle))
suppressMessages(library(flexclust))
suppressMessages(library(mcclust))
全部不報錯后,我們開始第一個包的學(xué)習(xí)。
2 scRNAseq Package
需要自行下載安裝一些必要的R包,主要是scRNAseq,然后是其它一些輔助包用來探索這個數(shù)據(jù)集。
if (!requireNamespace("Rtsne"))
install.packages("Rtsne")
if (!requireNamespace("FactoMineR"))
install.packages("FactoMineR")
if (!requireNamespace("factoextra"))
install.packages("factoextra")
if (!requireNamespace("BiocManager"))
install.packages("BiocManager")
if (!requireNamespace("scater"))
BiocManager::install("scater")
if (!requireNamespace("scRNAseq"))
BiocManager::install("scRNAseq")
if (!requireNamespace("M3Drop"))
BiocManager::install("M3Drop")
if (!requireNamespace("ROCR"))
BiocManager::install("ROCR")
##加載R包,前提是已經(jīng)成功安裝了
rm(list = ls()) # clear the environment
#load all the necessary libraries
options(warn=-1) # turn off warning message globally
suppressMessages(library(scater))
suppressMessages(library(scRNAseq))
library(ggplot2)
library(tidyr)
library(cowplot)
library("FactoMineR")
library("factoextra")
library("ROCR")
scRNAseq R包中的數(shù)據(jù)集
這個包內(nèi)置的是 Pollen et al. 2014 數(shù)據(jù)集,人類單細(xì)胞細(xì)胞,分成4類,分別是 pluripotent stem cells 分化而成的 neural progenitor cells (“NPC”) ,還有 “GW16” and “GW21” ,“GW21+3” 這種孕期細(xì)胞,理解這些需要一定的生物學(xué)背景知識,如果不感興趣,可以略過。
不過本例子只使用了數(shù)據(jù)集的4種細(xì)胞類型而已,因為 scRNAseq 這個R包就提供了這些,完整的數(shù)據(jù)是 23730 features,301 samples, 地址為:
https://hemberg-lab.github.io/scRNA.seq.datasets/human/tissues/
這里面的表達(dá)矩陣是由 RSEM (Li and Dewey 2011) 軟件根據(jù) hg38 RefSeq transcriptome 得到的,總是130個文庫,每個細(xì)胞測了兩次,測序深度不一樣。
library(scRNAseq)
## ----- Load Example Data -----
data(fluidigm)
fluidigm<-ReprocessedFluidigmData()##作者修改了提取數(shù)據(jù)的方法,需要多運行這一步
ct <- floor(assays(fluidigm)$rsem_counts)##counts含有小數(shù),因此需要floor()
ct[1:4,1:4]
sample_ann <- as.data.frame(colData(fluidigm))
DT::datatable(sample_ann)
先探索表型信息
前面說到,這個數(shù)據(jù)集是130個文庫,每個細(xì)胞測了兩次,測序深度不一樣,這130個細(xì)胞,分成4類,分別是: pluripotent stem cells 分化而成的 neural progenitor cells (“NPC”) ,還有 “GW16” and “GW21” ,“GW21+3” 這種孕期細(xì)胞。
批量,粗略的看一看各個細(xì)胞的一些統(tǒng)計學(xué)指標(biāo)的分布情況:
```{r fig.width=10, fig.height=15}##rmarkdown畫圖技巧
box <- lapply(colnames(sample_ann[,1:19]),function(i) {
dat <- sample_ann[,i,drop=F]
dat$sample=rownames(dat)
## 畫boxplot
ggplot(dat, aes('all cells', get(i))) +
geom_boxplot() +
xlab(NULL)+ylab(i)
})
plot_grid(plotlist=box, ncol=5 )
# ggsave(file="stat_all_cells.pdf")

因為進行了簡單探索,對表型數(shù)據(jù)就有了把握,接下來可以進行一定程度的過濾,因為細(xì)節(jié)太多,這里重點是批量,代碼技巧非常值得學(xué)習(xí)。教程略過了這一部分。
pa <- colnames(sample_ann[,c(1:9,11:16,18,19)])
tf <- lapply(pa,function(i) {
# i=pa[1]
dat <- sample_ann[,i]
dat <- abs(log10(dat))
fivenum(dat)
(up <- mean(dat)+2*sd(dat))
(down <- mean(dat)- 2*sd(dat) )
valid <- ifelse(dat > down & dat < up, 1,0 )
})
tf <- do.call(cbind,tf)
choosed_cells <- apply(tf,1,function(x) all(x==1))
table(sample_ann$Biological_Condition)
sample_ann=sample_ann[choosed_cells,]
table(sample_ann$Biological_Condition)
ct <- ct[,choosed_cells]
再探索基因表達(dá)情況
ct[1:4,1:4]
counts <- ct
fivenum(apply(counts,1,function(x) sum(x>0) ))
boxplot(apply(counts,1,function(x) sum(x>0) ))
fivenum(apply(counts,2,function(x) sum(x>0) ))
hist(apply(counts,2,function(x) sum(x>0) ))
choosed_genes=apply(counts,1,function(x) sum(x>0) )>0
table(choosed_genes)
counts <- counts[choosed_genes,]
##查看一下表達(dá)不為0的基因個數(shù)
> table((apply(counts,1,function(x) sum(x>0)>0 )))
TRUE
17096
幾乎沒有基因在所有細(xì)胞都表達(dá),中位線為35,如果基因在35個細(xì)胞內(nèi)不表達(dá)即可過濾掉(閾值)。

接下來要利用自己的常規(guī)轉(zhuǎn)錄組數(shù)據(jù)分析知識。
細(xì)胞之間的所有的基因的表達(dá)量的相關(guān)性
下面的計算,都是基于log后的表達(dá)矩陣。
dat <- log2(edgeR::cpm(counts) + 1)
dat[1:4, 1:4]
dat_back <- dat
先備份這個表達(dá)矩陣,后面的分析都用得上。
exprSet <- dat_back
colnames(exprSet)
pheatmap::pheatmap(cor(exprSet))
group_list <- sample_ann$Biological_Condition
tmp <- data.frame(g = group_list)
rownames(tmp) <- colnames(exprSet)
##組內(nèi)的樣本的相似性應(yīng)該是要高于組間的!
pheatmap::pheatmap(cor(exprSet), annotation_col = tmp)
dim(exprSet)
exprSet = exprSet[apply(exprSet, 1, function(x)
sum(x > 1) > 5), ]
dim(exprSet)
dim(exprSet)
exprSet <- exprSet[names(sort(apply(exprSet, 1, mad), decreasing = T)[1:500]), ]
dim(exprSet)
M <-cor(log2(exprSet + 1))
tmp <- data.frame(g = group_list)
rownames(tmp) <- colnames(M)
pheatmap::pheatmap(M, annotation_col = tmp)
table(sample_ann$LibraryName)

可以看到,從細(xì)胞的相關(guān)性角度來看,到NPC跟另外的GW細(xì)胞群可以區(qū)分的很好,但是GW本身的3個小群體并沒有那么好的區(qū)分度。
而且簡單選取top的sd的基因來計算相關(guān)性,并沒有很明顯的改善。
但是可以看到每個細(xì)胞測了兩次,所以它們的相關(guān)性要好于其它同類型的細(xì)胞。
對表達(dá)矩陣進行簡單的層次聚類
如果計算機資源不夠,這里可以先對基因進行一定程度的挑選,最簡單的就是選取top的sd的基因,這里略。
dat <- dat_back
hc <- hclust(dist(t(dat)))
plot(hc,labels = FALSE)
clus <- cutree(hc, 4) #對hclust()函數(shù)的聚類結(jié)果進行剪枝,即選擇輸出指定類別數(shù)的系譜聚類結(jié)果。
group_list <- as.factor(clus) ##轉(zhuǎn)換為因子屬性
table(group_list) ##統(tǒng)計頻數(shù)
table(group_list,sample_ann$Biological_Condition)

可以看到GW16和GW21是很難區(qū)分開來的,如果是普通的層次聚類的話。
然后看看最常規(guī)的PCA降維結(jié)果
降維算法很多,詳情可以去自行搜索學(xué)習(xí),比如:
- 主成分分析PCA
- 多維縮放(MDS)
- 線性判別分析(LDA)
- 等度量映射(Isomap)
- 局部線性嵌入(LLE)
- t-SNE
- Deep Autoencoder Networks
這里只介紹 PCA 和 t-SNE
dat <- dat_back
dat <- t(dat)
dat <- as.data.frame(dat)
plate <- sample_ann$Biological_Condition # 這里定義分組信息
dat <- cbind(dat, plate) #cbind根據(jù)列進行合并,即疊加所有列 #矩陣添加批次信息
dat[1:4, 1:4]
table(dat$plate)
# The variable plate (index = ) is removed
# before PCA analysis
dat.pca <- PCA(dat[, -ncol(dat)], graph = FALSE)
head(dat.pca$var$coord) ## 每個主成分的基因重要性占比
head(dat.pca$ind$coord) ## 每個細(xì)胞的前5個主成分取值。
fviz_pca_ind(
dat.pca,
#repel =T,
geom.ind = "point",
# show points only (nbut not "text")
col.ind = dat$plate,
# color by groups
#palette = c("#00AFBB", "#E7B800"),
addEllipses = TRUE,
# Concentration ellipses
legend.title = "Groups"
)
同樣的,很明顯可以看到NPC跟另外的GW細(xì)胞群可以區(qū)分的很好,但是GW本身的3個小群體并沒有那么好的區(qū)分度。
接著是稍微高大上的tSNE降維
因為計算量的問題,這里先選取PCA后的主成分,然進行tSNE,當(dāng)然,也有其它做法,比如選取變化高的基因,顯著差異基因等等。
# 選取前面PCA分析的5個主成分。
dat_matrix <- dat.pca$ind$coord
# Set a seed if you want reproducible results
set.seed(42)
library(Rtsne)
# 如果使用原始表達(dá)矩陣進行 tSNE耗時很可怕,dat_matrix = dat_back
# 出現(xiàn)Remove duplicates before running TSNE 則check_duplicated = FALSE
# tsne_out <- Rtsne(dat_matrix,pca=FALSE,perplexity=30,theta=0.0, check_duplicates = FALSE) # Run TSNE
tsne_out <- Rtsne(dat_matrix,perplexity=10)
plate <- sample_ann$Biological_Condition # 這里定義分組信息
plot(tsne_out$Y,col= rainbow(4)[as.numeric(as.factor(plate))], pch=19)
對PCA或者tSNE結(jié)果進行kmeans或者dbscan算法聚類
降維是降維,聚類是聚類,需要理解其中的區(qū)別。
降維與否,不同的降維算法選擇,不同參數(shù)的選擇得到的結(jié)果都不一樣。
聚類也是一樣,不同的算法,不同的參數(shù)。
# 前面我們的層次聚類是針對全部表達(dá)矩陣,這里我們?yōu)榱斯?jié)省計算量,可以使用tsne_out$Y這個結(jié)果
head(tsne_out$Y)
opt_tsne=tsne_out$Y
table(kmeans(opt_tsne,centers = 4)$clust)
plot(opt_tsne, col=kmeans(opt_tsne,centers = 4)$clust, pch=19, xlab="tSNE dim 1", ylab="tSNE dim 2")
library(dbscan)
plot(opt_tsne, col=dbscan(opt_tsne,eps=3.1)$cluster, pch=19, xlab="tSNE dim 1", ylab="tSNE dim 2")
table(dbscan(opt_tsne,eps=3.1)$cluster)
# 比較兩個聚類算法區(qū)別
table(kmeans(opt_tsne,centers = 4)$clust,dbscan(opt_tsne,eps=3.1)$cluster)
3 M3Drop Package分析scRNA數(shù)據(jù)
首先構(gòu)建M3Drop需要的對象
library(M3Drop)
Normalized_data <- M3DropCleanData(counts,
labels = sample_ann$Biological_Condition ,
is.counts=TRUE, min_detected_genes=2000)
##查看對象
dim(Normalized_data$data)
length(Normalized_data$labels)
class(Normalized_data)
str(Normalized_data)
這個包設(shè)計比較簡單,并沒有構(gòu)建S4對象,只是一個簡單的list而已。
統(tǒng)計學(xué)算法 Michaelis-Menten
需要深入讀該文章,了解其算法,這里略過,總之它對單細(xì)胞轉(zhuǎn)錄組的表達(dá)矩陣進行了一系列的統(tǒng)計檢驗。
fits <- M3DropDropoutModels(Normalized_data$data)
# Sum absolute residuals
data.frame(MM=fits$MMFit$SAr, Logistic=fits$LogiFit$SAr,
DoubleExpo=fits$ExpoFit$SAr)
# Sum squared residuals
data.frame(MM=fits$MMFit$SSr, Logistic=fits$LogiFit$SSr,
DoubleExpo=fits$ExpoFit$SSr)

找差異基因
DE_genes <- M3DropFeatureSelection(Normalized_data$data,
mt_method="fdr", mt_threshold=0.01)
dim(DE_genes)
head(DE_genes)
這里是針對上面的統(tǒng)計結(jié)果來的。

針對差異基因畫熱圖
par(mar=c(1,1,1,1))
heat_out <- M3DropExpressionHeatmap(DE_genes$Gene, Normalized_data$data,
cell_labels = Normalized_data$labels)
可視化了解一下找到的差異基因在不同的細(xì)胞類型的表達(dá)分布情況。

聚類
這里可以重新聚類后,針對自己找到的類別來分別找marker基因,不需要使用測試數(shù)據(jù)自帶的表型信息。
cell_populations <- M3DropGetHeatmapCellClusters(heat_out, k=4)
library("ROCR")
marker_genes <- M3DropGetMarkers(Normalized_data$data, cell_populations)
table(cell_populations,Normalized_data$labels)
每個類別的marker genes
head(marker_genes[marker_genes$Group==4,],20)
marker_genes[rownames(marker_genes)=="FOS",]
也可以針對這些 marker genes去畫熱圖,當(dāng)然,得根據(jù)AUC和P值來挑選符合要求的差異基因去繪圖。
par(mar=c(1,1,1,1))
choosed_marker_genes=as.character(unlist(lapply(split(marker_genes,marker_genes$Group), function(x) (rownames(head(x,20))))))
heat_out <- M3DropExpressionHeatmap(choosed_marker_genes, Normalized_data$data, cell_labels = cell_populations)
如果遇到Error in plot.new() : figure margins too large報錯,則單獨將heat_out這行命令復(fù)制出來運行
對感興趣基因集進行注釋
通常是GO/KEGG等數(shù)據(jù)庫,通常是超幾何分布,GSEA,GSVA等算法。
這里就略過。
顯示運行環(huán)境
sessionInfo()
下一篇我們繼續(xù)用單細(xì)胞的R包來處理數(shù)據(jù)集。
加油!我們下一篇再見!