(Smartseq2) single cell RNA-seq分析練習

這次跟著課程(Smartseq2 scRNA小鼠發育學習筆記-1-前言及上游介紹)要練習的文章是:Dissecting Cell Lineage Specification and Sex Fate Determination in Gonadal Somatic Cells Using Single-Cell Transcriptomics
課程里是從下載sra文件開始的,但是由于這篇文章的數據實在是太大了。。。

都下載下來的話,按照我這網速,可能要一年以后才能下載完了。所以我直接從課程的第二講開始練習(Smartseq2 scRNA小鼠發育學習筆記-2-根據表達矩陣進行分群)。關于單細胞測序的數據如何批量下載,如何比對,還有featureCount定量,我在上一個練習里有寫到(單細胞測序實戰(第一部分))。這次主要練習下游的分析部分,這部分是最重要的,也是核心部分。還有個原因就像課程說的(Smartseq2 scRNA小鼠發育學習筆記-1-前言及上游介紹):

smartseq2得到的兩個R1、R2都是測序信息,于是它的操作和我們常規bulk轉錄組是類似的。可以用hisat2+featureCounts進行操作

需要明確的是:文章表明了6個發育時期、4群細胞、2個發育軌跡這三種細胞屬性

首先先下載原始count矩陣https://raw.githubusercontent.com/IStevant/XX-XY-mouse-gonad-scRNA-seq/master/data/female_count.Robj
作者rpkm標準化后的矩陣https://github.com/IStevant/XX-XY-mouse-gonad-scRNA-seq/raw/master/data/female_rpkm.Robj

(一)過濾重復的細胞,構建表達矩陣(使用原始count矩陣)

#導入作者上傳的原始矩陣
> load(file="female_count.Robj")
> load(file="female_rpkm.Rdata")
# 去掉重復細胞(作者用“rep”進行了標記),先看一下哪些列是重復的
> grep("rep",colnames(female_count))
[1] 257 #第257列是重復的
# 直接對細胞和基因過濾
female_count <- female_count[rownames(female_count) %in% rownames(females),!colnames(female_count) %in% grep("rep",colnames(female_count), value=TRUE)]
# %in%相當于match()函數的一個縮寫。用來判斷一個數組或矩陣(前面的)是否包含在另一個數組或矩陣(后面的)里。
#看一下過濾之后的
> female_count[1:3,1:3]
      E10.5_XX_20140505_C01_150331_1 E10.5_XX_20140505_C02_150331_1 E10.5_XX_20140505_C03_150331_1
eGFP                           19582                            526                           4786
Gnai3                           2218                            122                              4
Pbsn                               0                              0                              0
#保存一下
> save(female_count,file = 'female_count.Rdata')

(二)tSNE分析(Seurat方法)
在分析之前,先簡單的了解一下什么是Seurat,這是這個包的官方網站(SATIJA LAB),據說這個包今年剛升過級,這個包還可以很友好的直接讀取10x Genomics的輸出結果(單細胞轉錄組測序分析--初探Seurat)。有幾個比較好的文章對于這個包進行介紹:
1.Seurat使用教程(v3.0)
2.單細胞Seurat包升級,換湯不換藥
3.單細胞轉錄組測序分析--初探Seurat

下面進行分析,首先要對細胞分群,按照不同的發育時期來獲取細胞群:

> load(file="female_count.Rdata")
> dim(females) #看一下多少行,多少列
[1] 21083   563
> head(colnames(females)) #看一下列名
[1] "E10.5_XX_20140505_C01_150331_1" "E10.5_XX_20140505_C02_150331_1" "E10.5_XX_20140505_C03_150331_1"
[4] "E10.5_XX_20140505_C04_150331_2" "E10.5_XX_20140505_C06_150331_2" "E10.5_XX_20140505_C07_150331_3"
#按照胚胎的天數來分細胞群,所以要按照E10.5這部分來劃分
> female_stages <- stringr::str_split(colnames(females),'_', simplify = T)[,1] 
#str_split意思是按照模式分割字符串,這里是按照行名里的下劃線分割,后面的1是第一個下劃線的意思
> head(female_stages)
[1] "E10.5" "E10.5" "E10.5" "E10.5" "E10.5" "E10.5"
#表達矩陣里有多少列(多少細胞),female_stages里就有多少元素,把列名賦值給它
> names(female_stages) <- colnames(females) 
> table(female_stages)
female_stages
E10.5 E11.5 E12.5 E13.5 E16.5    P6 
   68   100   103    99    85   108 
這是分群的結果,這一看到所有的細胞都被標記了是哪一個胚胎時間的

現在就得到了6個不同的群,每個群的細胞數不同
下面使用seurat進行tSNE分析,分幾步進行:
(1)構建對象

#安裝seurat包
> install.packages('Seurat')
> library(Seurat)
#構建對象
> sce_female <- CreateSeuratObject(counts = female_count, 
                                 project = "sce_female", 
                                 min.cells = 1, min.features = 0)
# 這一步還有過濾功能,基因至少在min.cells個細胞中表達,每個細胞中至少表達min.genes個基因/features。這句的代碼是這個基因至少要在1個細胞里有表達,不然就被過濾掉。
> sce_female
An object of class Seurat 
16765 features across 563 samples within 1 assay 
Active assay: RNA (16765 features)

view一下這個sce_female:

點開里面的meta.data,可以看到UMI的情況:

我搜了一下網上,想知道這些都是些啥,在這篇文章里得知(單細胞轉錄組測序分析--初探Seurat):創建完Seurat對象后,Seurat將數據保存在不同的slot中,如sce_female@raw.data, sce_female@data, sce_female@meta.data, sce_female@ident,其中meta.data存放的是每個細胞的統計數據如UMI數目,gene數目等,ident此時存放的是project信息。

(2)添加樣品注釋

#使用AddMetaData添加meta信息
> sce_female <- AddMetaData(object = sce_female, 
                          metadata = apply(female_count, 2, sum), 
                          col.name = 'nUMI_raw')
> sce_female <- AddMetaData(object = sce_female, 
                          metadata = female_stages, 
                          col.name = 'female_stages') #把上面我們分的細胞的不同時期加到這個對象里

(3)標準化
Seurat官網上對于標準化的這部分是這樣寫的:

After removing unwanted cells from the dataset, the next step is to normalize the data. By default, we employ a global-scaling normalization method “LogNormalize” that normalizes the feature expression measurements for each cell by the total expression, multiplies this by a scale factor (10,000 by default), and log-transforms the result. Normalized values are stored in @data.
去除掉不想要的細胞以后,下一步就是標準化。默認值下,我們使用global-scaling標準化方法,稱為“LogNormalize”。對每個基因進行標準化:該基因的UMI除以該細胞內轉錄物的總UMI并乘以10000(默認值),再取log值作為結果。

> sce_female <- NormalizeData(sce_female) #這是簡化版的代碼,也是官方推薦使用的
#這句代碼的完整格式應該是這樣:
#sce_female <- NormalizeData(object =sce_female,normalization.method = "LogNormalize", scale.factor = 10000)

Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

> sce_female[["RNA"]]@data[1:3,1:3] #看一眼標準化之后的
3 x 3 sparse Matrix of class "dgCMatrix"
      E10.5_XX_20140505_C01_150331_1 E10.5_XX_20140505_C02_150331_1 E10.5_XX_20140505_C03_150331_1
eGFP                        3.753731                      0.7024916                      2.8485868
Gnai3                       1.744141                      0.2121183                      0.0135009
Cdc45                       2.001816                      1.6581178                      0.6510173

(4)找差異基因Identification of highly variable features (feature selection)

> sce_female <- FindVariableFeatures(sce_female, 
                                    selection.method = "vst", 
                                    nfeatures = 2000)
# nfeatures = 2000是默認值
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# HVGs可視化
> VariableFeaturePlot(sce_female)

如果想看上面這個圖里偏上的紅點都是什么基因,還可以再用兩句代碼:

> top10 <- head(VariableFeatures(sce_female), 10)
> plot1<- VariableFeaturePlot(sce_female)
> plot2 <- LabelPoints(plot = plot1, points = top10, repel = TRUE)
> plot2

(5)數據比例化(調整數據范圍)
在降維之前還可以有一步就是數據的比例化,官方是這樣解釋為什么要進行這一步的:

(1)Shifts the expression of each gene, so that the mean expression across cells is 0
(2)Scales the expression of each gene, so that the variance across cells is 1
(3)This step gives equal weight in downstream analyses, so that highly-expressed genes do not dominate
The results of this are stored in pbmc[["RNA"]]@scale.data
說的簡單一點就是,有些基因的表達量非常高,會掩蓋掉低表達基因的變化,這一步就是降低高表達基因的影響。

#默認只對FindVariableFeatures得到的HVGs進行操作
> sce_female <- ScaleData(object = sce_female, 
                         vars.to.regress = c('nUMI_raw'), 
                         model.use = 'linear', 
                         use.umi = FALSE)
#vars.to.regress的意思就是需要去除的變異來源。該函數會先進行先行回歸分析,然后再進行數據的比例化

Regressing out nUMI_raw
  |=============================================================================================================| 100%
Centering and scaling data matrix
  |=============================================================================================================| 100%

(6)PCA降維
對于降維:PCA和tSNE都是數據降維分析方法,PCA屬于線性降維,tSNE屬于非線性降維(單細胞轉錄組測序分析--初探Seurat)。
為什么要降維?單細胞測序數據是一個高維的復雜數據。降維,就是把高維數據通過優化保留原始數據中的關鍵特征后投射到低維空間,從而可以通過二維或三維的形式把數據展示出來。先執行PCA分析,使高維數據的信息最大程度保留在低維數據中。

> sce_female <- RunPCA(sce_female, 
                      features = VariableFeatures(object = sce_female))
#然后會彈出下面一堆:
PC_ 1 
Positive:  Kctd14, Cgn, Itga6, Kitl, Gstm2, Bhlhe41, Lzts1, eGFP, Serpinb6a, Ttyh2 
       Soat1, Ifitm1, Rnf213, Gstm1, Idh1, Pank1, Anxa2, Gpr56, Klhl23, Sdc4 
       Hmgcs2, Laptm4b, Tmprss13, Tmem206, Clu, Rgs11, Serpinb6b, Gadd45g, Cpa2, Gatm 
Negative:  Col1a2, Col1a1, Sfrp1, Sept11, Ncam1, Ptn, Mmp2, Fn1, Col3a1, Hmga2 
       Nrep, Sparcl1, Tcf21, Mfap4, Sox11, Meis1, Cxcl12, Nfib, Bgn, Cnn2 
       Pdgfra, Efna5, Dcn, Cdh11, Fstl1, Fblim1, Vcan, Top2a, Tuba1a, Lpar1 
PC_ 2 
Positive:  Itih5, Cfh, Dcn, Col6a2, Igf1, Akr1cl, Ogn, Col1a1, Lama2, Sparcl1 
       Lum, Zbtb20, Cd34, Col6a1, Ptrf, Rarres2, Col1a2, Bgn, Gas6, Lrrc17 
       Cped1, Col4a4, Srpx2, Col6a3, Prss35, Plxnc1, Serpine2, Slc26a7, Tcf21, Pdlim3 
Negative:  Hmga2, Peg3, Mest, Sox11, Cdkn1c, Rrm2, Rgs5, Ccnb1, Aldh1a2, Ccnd1 
       Oraov1, Asb4, Tpx2, Cenpf, Flrt3, Hapln1, Kif20a, Ect2, Top2a, Meis1 
       Cenpe, F11r, Kif22, Bub1, Sfrp2, Kif2c, Krt18, Ube2c, Ncaph, Sulf1 
PC_ 3 
Positive:  Cdkn1c, Ifitm1, Peg3, Fstl1, Acaa2, Nfib, Lzts1, Cgn, Anxa6, Tnfrsf19 
       Lhx9, Laptm4b, Col3a1, Sema6d, Col1a1, Sulf1, Zfp57, Serpinb6b, Bgn, Timp3 
       eGFP, Anxa2, Lgr4, Col1a2, Colec12, Itm2a, Hmcn1, Mest, Serpini1, Bhlhe41 
Negative:  Serpine2, Socs2, Inha, Kazald1, Lect1, Ephx2, Ptges, Hsd3b1, Hsd17b1, Apoa1 
       Myo1e, Ubash3b, Esr2, Fam13a, Arhgap31, Gls, Gja1, Slc18a2, Ablim1, Tanc2 
       Slc26a7, Map1b, Sytl4, Myo5c, Tenm4, Ivns1abp, Thbs1, Epn2, Top2a, Akr1c14 
PC_ 4 
Positive:  Top2a, Prc1, Ube2c, Ccnb1, Cenpf, Tpx2, Plk1, Kif22, Ckap2l, Bub1 
       Kif23, Mki67, Aspm, Cdk1, eGFP, Bub1b, Ccna2, Kif2c, Ncaph, Ect2 
       Cenpe, Cdc25c, Ccnb2, Kif20a, Ifitm1, Nr6a1, Zwilch, Sgol1, Rrm2, Gm3550 
Negative:  Alcam, Ptgs1, Fras1, Gata2, Upk1b, Ccnd2, Dpp4, Runx1t1, Pkhd1l1, Frem2 
       Vstm2a, Cpa6, Efna5, Nfib, Itm2a, Flrt1, Mn1, Sdc4, Plscr2, Gpm6a 
       Sema3c, Egr1, Mybpc1, Btg2, Krt18, Atp2b1, Zfp36, Sorbs2, Timp2, Ece1 
PC_ 5 
Positive:  Nup62cl, Cyp11a1, Pnlip, Gadd45g, Sphkap, Asb4, Pnliprp2, Akr1cl, Inha, Plac1 
       Gfra3, Asns, Siglecg, Foxp2, Pls3, Nefm, St3gal5, Adam8, Mc2r, Vav3 
       Gk5, Cpa1, Sprr2d, Tenm4, Hmga2, Cxcl12, Gbp5, Trpc7, Ttc38, Inhbb 
Negative:  Sorbs2, Cav1, Btg2, Pdpn, Lgr5, Prc1, Egr1, Cst12, Mt1, Ccnb1 
       Ube2c, Fos, Zfp36, Aspm, Sdc4, Cenpf, Ckap2l, Top2a, Tpx2, Mki67 
       Egr2, Cdk1, Kif23, Plk1, Tnfrsf19, Kif20a, Pde8b, Bub1, Kif22, Enpp2

Seurat包提供了多種PCA可視化的方法,感興趣的同學可以參考:https://satijalab.org/seurat/v3.1/pbmc3k_tutorial.html官網學習。這里只舉例一種:

> DimPlot(sce_female, reduction = "pca")

還可以畫個熱圖,舉個例子,畫PC_1和PC_2兩個dim的熱圖:

> DimHeatmap(object = sce_female, dims = 1:2, cells = 500, balanced = TRUE)

(7)降維以后聚類
在進行聚類分析之前,需要選擇使用對少個主成分進行計算。每個主成分實際上代表的是相關基因集的信息,因此確定多少個主成分是一個重要的步驟,我們可以根據PCElbowPlot函數來判斷。

#Seurat采用的是基于圖形的聚類方法,即利用PCA空間中的歐幾里德距離構造一個KNN圖。官網上寫了一堆數學概念,我也看不懂。。。
> sce_female <- FindNeighbors(sce_female, dims = 1:20)
Computing nearest neighbor graph
Computing SNN
> sce_female <- FindClusters(sce_female, resolution = 0.3)
#官方解釋:將resolution參數設置在0.4-1.2之間,對于3K左右的單細胞數據集通常會得到良好的結果。對于較大的數據集,最佳分辨率通常會增加。課程里這里用了0.3,為了盡量還原課程里的圖,我也用了0.3。(resolution會影響聚類的個數)

(8)tSNE

#在進行tSNE之前要先確定有多少個主成分,可以用PCElbowPlot函數來看
> ElbowPlot(sce_female)

可以看到,拐點出現在9左右,所以我們可以選擇9來進行聚類分析。

(9)tSNE可視化
Seurat提供了幾種非線性的降維技術,如tSNE和UMAP。

> sce_female_tsne <- RunTSNE(sce_female, dims = 1:9)
# 6個發育時間
> DimPlot(object = sce_female_tsne, reduction = "tsne",
        group.by = 'female_stages')
# 4個cluster
> DimPlot(sce_female_tsne, reduction = "tsne")

如果用UMAP來降維:

> sce_female_umap <- RunUMAP(sce_female, dims = 1:9)
> DimPlot(sce_female_umap, reduction = "umap",group.by = 'female_stages')
6個發育時期的可視化
> DimPlot(sce_female_umap, reduction = "umap")
4個cluster的可視化

(三)tSNE分析(DBSCAN、kmeans方法)
上面用了Seurat包做了分群,課程里還用了DBSCAN方法跑了一遍,所以我也練習了一下。

# 這個運行會非常慢!
> if(T){
  library(Rtsne)
  N_tsne <- 10 
  # 其實這里應該多運行一些,例如N_tsne <- 50,但是會非常非常慢。。。
  tsne_out <- list(length = N_tsne)
  KL <- vector(length = N_tsne)
  set.seed(1234)
  for(k in 1:N_tsne)
  {
    tsne_out[[k]]<-Rtsne(t(log2(females+1)),initial_dims=30,verbose=FALSE,check_duplicates=FALSE,
                         perplexity=27, dims=2,max_iter=5000)
    KL[k]<-tail(tsne_out[[k]]$itercosts,1)
    print(paste0("FINISHED ",k," TSNE ITERATION"))
  }
  names(KL) <- c(1:N_tsne)
  opt_tsne <- tsne_out[[as.numeric(names(KL)[KL==min(KL)])]]$Y
#在Y里儲存了畫圖坐標
}

這個代碼運行的時候,會彈出來一堆一下的東西:

[1] "FINISHED 1 TSNE ITERATION"
[1] "FINISHED 2 TSNE ITERATION"
[1] "FINISHED 3 TSNE ITERATION"
[1] "FINISHED 4 TSNE ITERATION"
[1] "FINISHED 5 TSNE ITERATION"
[1] "FINISHED 6 TSNE ITERATION"
[1] "FINISHED 7 TSNE ITERATION"
[1] "FINISHED 8 TSNE ITERATION"
[1] "FINISHED 9 TSNE ITERATION"
[1] "FINISHED 10 TSNE ITERATION"
# DBSCAN結果
> library(dbscan)
> plot(opt_tsne,  col=dbscan(opt_tsne,eps=3.1)$cluster, 
     pch=19, xlab="tSNE dim 1", ylab="tSNE dim 2")
DBSCAN方法
# kmeans方法
plot(opt_tsne,  col=kmeans(opt_tsne,centers = 4)$clust, 
     pch=19, xlab="tSNE dim 1", ylab="tSNE dim 2")
kmeans方法

(四)標記基因可視化
這一部分將跟著課程(Smartseq2 scRNA小鼠發育學習筆記-3-標記基因可視化)進行練習。我們已經把細胞分了群,接下來就要分析一下這些群間的差異性。Seurat包也可以做這個事情,FindAllMarkers能夠同時計算所有亞群的差異性(分別計算每個亞群與剩下的所有細胞的差異性)。但課程里寫到原文作者根據胚胎細胞發育的不同時期,選取了一些能代表不同時期的特異性marker進行后續分析。所以這里我還是跟隨教程走一遍。

目標:根據之前分析的6個發育時期和4個cluster的tSNE結果,畫一些marker基因的熱圖、小提琴圖。
首先要明確作者選了哪些基因(這些基因在原文中作者有提到是分別代表了哪些細胞群的marker基因):

# 作者選擇的14個marker基因
> markerGenes <- c(
  "Nr2f1",
  "Nr2f2",
  "Maf",
  "Foxl2",
  "Rspo1",
  "Lgr5",
  "Bmp2",
  "Runx1",
  "Amhr2",
  "Kitl",
  "Fst",
  "Esr2",
  "Amh",
  "Ptges"
)

小提琴圖,可以直接查看選取的這些marker基因在不同的cluster里的表達情況:

> VlnPlot(object = sce_female_tsne, features =  markerGenes , 
        pt.size = 0.2,ncol = 4)

熱圖:

> FeaturePlot(object = sce_female_tsne, features = markerGenes ,
            pt.size = 0.2,ncol = 3)
熱圖太大了,我就截取了一部分

如果是想單獨畫一個箱線圖(比如只畫Nrf2f這個基因):

# 分類信息
> group <- Seurat::Idents(sce_female)
## 表達矩陣
> nr2f2 <- as.numeric(log(female_count['Nr2f2',]+1))
#出圖
> boxplot(nr2f2~group)

覺得丑?那就畫個看起來高大上的小提琴圖吧。用ggviolin畫

#nrf2f的小提琴圖
> df <- data.frame(expr=nr2f2,
                 group=group) #首先整一個data.frame,以為ggplot要用data.frame才行

看一下這個df長什么樣

> view(df)
這是所有細胞的nr2f2的表達量,還有它們的分組情況0,1,2,3
> female_clusterPalette <- c(
  "#560047", 
  "#a53bad", 
  "#eb6bac", 
  "#ffa8a0"
) #這一步是給小提琴圖上顏色
> my_comparisons <- list( c("0", "1"), c("1", "2"), c("2", "3") ) #還想給這四組兩兩比較
> ggviolin(df, "group", "expr", fill = "group",
         palette = female_clusterPalette,
         add = "boxplot", add.params = list(fill = "white"))+
  stat_compare_means(comparisons = my_comparisons)
#這里"group"和"expr"分別代表了x軸和y軸

(五)monocle V2進行差異分析
這一部分按照教程(Smartseq2 scRNA小鼠發育學習筆記-4-差異分析及功能注釋)來練習。現在就要對之前分出來的4群細胞進行差異分析。這部分主要是利用原文文獻作者上傳的代碼來進行分析。另外,ROTS包也可以用來進行單細胞測序的差異分析,我這里沒有練習,之后有時間可以再練習一下。具體ROTS包流程代碼可見:Smartseq2 scRNA小鼠發育學習筆記-4-差異分析及功能注釋

(1)準備表達矩陣和分群信息

#獲取6個發育時期
> head(colnames(female_count))
[1] "E10.5_XX_20140505_C01_150331_1" "E10.5_XX_20140505_C02_150331_1" "E10.5_XX_20140505_C03_150331_1" "E10.5_XX_20140505_C04_150331_2"
[5] "E10.5_XX_20140505_C06_150331_2" "E10.5_XX_20140505_C07_150331_3"
> female_stages <- sapply(strsplit(colnames(female_count), "_"), `[`, 1)
> names(female_stages) <- colnames(female_count)
> table(female_stages)
female_stages
E10.5 E11.5 E12.5 E13.5 E16.5    P6 
   68   100   103    99    85   108
#這部分跟前面是一樣的

接下來我用的是下載下來的clustering文件(https://github.com/IStevant/XX-XY-mouse-gonad-scRNA-seq/blob/master/data/female_clustering.csv):

> cluster <- read.csv('female_clustering.csv')
> female_clustering=cluster[,2];names(female_clustering)=cluster[,1]
> table(female_clustering)
female_clustering
 C1  C2  C3  C4 
240  90 190  43 

(2)構建對象
需要:表達矩陣、細胞信息、基因信息

# 表達矩陣
> dim(female_count)
# 細胞分群信息(包括6個stage和4個cluster)
> table(female_stages)
female_stages
E10.5 E11.5 E12.5 E13.5 E16.5    P6 
   68   100   103    99    85   108 
> table(female_clustering)
female_clustering
 C1  C2  C3  C4 
240  90 190  43
# 基因信息
> gene_annotation <- as.data.frame(rownames(female_count))
#開始構建
> library(monocle)

這里教程使用了文獻中的源代碼prepare_for_DE,作者把下面這些代碼包裝成一個function:

> prepare_for_DE <- function(count_matrix=count_matrix, clustering=clustering, stages=stages){
  # Prepare tables for monocle object
  expr_matrix <- as.matrix(count_matrix)
  sample_sheet <- data.frame(cells=names(count_matrix), stages=stages, cellType=clustering)
  rownames(sample_sheet)<- names(count_matrix)
  gene_annotation <- as.data.frame(rownames(count_matrix))
  rownames(gene_annotation)<- rownames(count_matrix)
  colnames(gene_annotation)<- "genes"
  pd <- new("AnnotatedDataFrame", data = sample_sheet)
  fd <- new("AnnotatedDataFrame", data = gene_annotation)
  
  # Create a CellDataSet from the relative expression levels
  HSMM <- newCellDataSet(
    as(expr_matrix, "sparseMatrix"),
    phenoData = pd,
    featureData = fd,
    lowerDetectionLimit=0.5,
    expressionFamily=negbinomial.size()
  )
  
  HSMM <- detectGenes(HSMM, min_expr = 5)
  # HSMM <- HSMM[fData(HSMM)$num_cells_expressed > 5, ]
  HSMM <- HSMM[fData(HSMM)$num_cells_expressed > 10, ]
  
  HSMM <- estimateSizeFactors(HSMM)
  HSMM <- estimateDispersions(HSMM)
  
  return(HSMM)
}

然后直接使用這個function:

#包裝好的函數只需要提供表達矩陣和細胞信息
> DE_female <- prepare_for_DE (
  female_count, 
  female_clustering, 
  female_stages
)

下面這一步是篩選那些差異較大的基因(FDR<0.05,也就是q值小于0.05),這里教程還是使用了文獻里的源代碼進行篩選。源代碼包成了一個包:

#第一次運行的話,需要自己運行一遍這個,這樣自己的R里就會儲存這個function,之后就可以直接調用了
> findDEgenes <- function(HSMM=HSMM, qvalue=qvalue){
  diff_test_res <- differentialGeneTest(
    HSMM,
    fullModelFormulaStr="~cellType",
    cores = 3
  )
  
  sig_genes_0.05 <- subset(diff_test_res, qval < 0.05)
  sig_genes_0.01 <- subset(diff_test_res, qval < 0.01)
  
  print(paste(nrow(sig_genes_0.05), " significantly DE genes (FDR<0.05).", sep=""))
  print(paste(nrow(sig_genes_0.01), " significantly DE genes (FDR<0.01).", sep=""))
  
  diff_test_res <- subset(diff_test_res, qval< qvalue)
  
  return(diff_test_res)
}

然后直接運行這個function:

> start_time <- Sys.time()
> female_DE_genes <- findDEgenes(
   DE_female, 
   qvalue=0.05
 )
[1] "4435 significantly DE genes (FDR<0.05)." #也就是說最后我們篩選出來了4435個差異顯著的基因
[1] "3268 significantly DE genes (FDR<0.01)."
> end_time <- Sys.time()
> end_time - start_time
Time difference of 1.661446 mins

得到了顯著的差異基因,需要知道這些基因都是屬于哪一個cluster的。這里文獻的作者仍然包了一個函數get_up_reg_clusters(),這個函數的作用是:先得到了每個差異基因在不同cluster的平均表達量,然后找平均表達量最大的那個cluster,就認為這個基因屬于這個cluster。get_up_reg_clusters源代碼是:

> get_up_reg_clusters <- function(count, clustering, DE_genes){
cluster_nb <- unique(clustering)
mean_per_cluster <- vector()
DE_genes <- DE_genes[order(rownames(DE_genes)),]
count <- count[order(rownames(count)),]
count_de_genes <- count[rownames(count) %in% DE_genes$genes,]
print(dim(count_de_genes))
for (clusters in cluster_nb) {
  # print(head(count_de_genes[,
  #         colnames(count_de_genes) %in% names(clustering[clustering==clusters])
  #     ]))
  mean <- rowMeans(
    as.matrix(count_de_genes[,
                             colnames(count_de_genes) %in% names(clustering[clustering==clusters])
                             ])
  )
  names(mean) <- clusters
  mean_per_cluster <- cbind(
    mean_per_cluster,
    mean
  )
}
colnames(mean_per_cluster) <- cluster_nb
up_reg_cluster <- colnames(mean_per_cluster)[apply(mean_per_cluster,1,which.max)]
de_genes_table <- data.frame(
  DE_genes,
  mean_per_cluster,
  cluster=up_reg_cluster
)

return(de_genes_table)
}

然后用我們最開始下載的RPKM矩陣

> load(file="female_rpkm.Rdata")
> de_clusters <- get_up_reg_clusters(
  females, 
  female_clustering, 
  female_DE_genes
)

(六)差異基因功能注釋
之前用了monocle分析得到了差異基因,接下來就是對這些差異基因進行注釋了。首先我們要先找到這些差異基因的基因名:

> de_genes <- subset(de_clusters, qval<0.05)
> length(de_genes$genes)
[1] 4435

基因的ID進行轉換:

基因ID轉換
> entrez_genes <- bitr(de_genes$genes, fromType="SYMBOL", 
                      toType="ENTREZID", 
                      OrgDb="org.Mm.eg.db")

NOTE:接下來一步,根據課程(Smartseq2 scRNA小鼠發育學習筆記-4-差異分析及功能注釋)里寫的,作者剔除掉了一個基因名

> entrez_genes <- entrez_genes[!entrez_genes$ENTREZID %in% "101055843",]
> length(entrez_genes$SYMBOL)
[1] 4281 #有些基因SYMBOL沒有對應的ENTREZID,所以少了100多個基因
#把那些存在ENTREZID的基因的基因名和cluster信息提取出來
> de_gene_clusters <- de_genes[de_genes$genes %in% entrez_genes$SYMBOL,
                             c("genes", "cluster")]
# 保持de_gene_clusters$genes的順序不變,將symbol變成entrez ID
> de_gene_clusters <- data.frame(
  ENTREZID=entrez_genes$ENTREZID[entrez_genes$SYMBOL %in% de_gene_clusters$genes],
  cluster=de_gene_clusters$cluster
)

現在看一下de_gene_clusters,可以看出來這4000多個差異基因的ENTREZID名字都有一個對應的cluster了:

下面就是把這些混在一起的cluster們都拆分出來,

> list_de_gene_clusters <- split(de_gene_clusters$ENTREZID, 
                                de_gene_clusters$cluster)

然后再看看我們拆分的情況:

這里就可以看到每一個cluster都有多少差異基因了

下面就是注釋的步驟了:

> formula_res <- compareCluster(
  ENTREZID~cluster, 
  data=de_gene_clusters, 
  fun="enrichGO", 
  OrgDb="org.Mm.eg.db",
  ont          = "BP",
  pAdjustMethod = "BH",
  pvalueCutoff  = 0.01,
  qvalueCutoff  = 0.05
)

最后就是可視化:
在教程里,大神用的是dotplot來畫圖,可奈何我的電腦不知道為何一直報錯。。。明明就是很簡單的一句代碼:

> dotplot(formula_res, showCategory=5)

解決了兩天也沒弄好,后來尋思著那就換一個包畫圖吧。。。在網上搜了好久,發現了這篇文章:聽說你也在畫dotplot,但是我不服! 文章里說“clusterProfiler的輸出你不用as.data.frame,就可以直接傳給ggplot2”,那我就用ggplot2試試吧

>  ggplot(formula_res, aes(Cluster, Description), showCategory=5) 
+   geom_point(aes(color=qvalue, size=GeneRatio)) + theme_bw()+scale_colour_gradient(low="#132B43",high="#56B1F7")

到此為止,smartseq2的單細胞測序基本的分析就做完了。因為我不做胚胎這塊,發育軌跡接觸的機會也幾乎沒有,所以沒有跟著教程做發育譜系可視化這一塊練習(Smartseq2 scRNA小鼠發育學習筆記-5-發育譜系推斷及可視化),有興趣和有需要的同學可以繼續練習這一塊。總之,需要深入學習的還有很多,這次練習的收獲就是初次接觸了Seurat包,也是單細胞測序分析的主流包。對于這些經常能用得到的包,還是多研究一下比較好,最好是能去官網閱讀一下說明書,加深理解。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375