最近在学单细胞的生信分析,学的有点懵。。。。先做点记录吧,后面在看看有什么要改的。
说起来,生信分析的B站上怎么全是直到这基本流程就结束的。。看文献后面应该还有很多。。不知道怎么学了。
建议:每步处理完之后都建议:
saveRDS(SZDX0224_val, file = "./Data/SZDX-0224_outs/SZDX0224_val.rds")
方便后面可以随时检查:
SZDX0224_val <- readRDS(file = "./Data/SZDX-0224_outs/SZDX0224_val.rds")
本文章结构:核心代码、部分函数解释、结果图
1、R包加载和安装
if(!require(multtest))BiocManager::install("multtest")
if(!require(Seurat))install.packages("Seurat")
if(!require(dplyr))install.packages("dplyr")
if(!require(patchwork))install.packages("patchwork")
if(!require(R.utils))install.packages("R.utils")
rm(list = ls());gc() #删除所有环境变量整理内存空间
2、数据读取
# 构建数据文件夹的相对路径
relative_path <- file.path(base_path, "Data", "SZDX-0224_report", "SZDX-4-0224 starsolo", "SZDX-4-0224", "filtered")
# 自动读取10X的数据,是一些tsv与mtx文件。
SZDX0224 <- Read10X(relative_path)
# 单细胞的分析一般都是利用Seurat包来实现的,所以我们也要转成Seurat的对象
SZDX0224_project <- CreateSeuratObject(counts = SZDX0224, project = "SZDX0224", min.cells = 0, min.features = 200)
在这里,我们使用的是自己的一个数据SZDX0224,用的是10x得到的。
其中CreatSeuratObject函数的参数:
CreateSeuratObject(counts = NULL, project = NULL, min.cells = 3, min.features = 200, sep = "_", group.by = NULL, block.by = NULL, merge.data = TRUE, do.normalize = TRUE, do.scale = TRUE, gene.column = 1, sample.names = NULL, expression.family = NegBinomial, nUMI = NULL, local.only = FALSE)
- counts(必需):一个矩阵或数据框,其中包含单细胞RNA测序的原始计数数据,行代表基因,列代表细胞/Barcode。矩阵里的数值就是对应的,含有该基因的细胞数(我们做实验都会有很多细胞)
- project(可选):一个字符串,表示你所使用的Seurat对象的名称或项目名称。在这里就是前面Read10x赋值的变量名。
- min.cells(可选):一个整数,指定一个细胞必须具有的最小基因数,否则将被排除在分析之外。(一个细胞有多个基因,根据实际情况,可修改设置进行过滤)
- min.feature(可选):一个整数,指定一个细胞必须具有的最小UMI(Unique Molecular Identifiers)数,否则将被排除在分析之外。(最小UMI数:UMI是每个转录RNA的身份证,进行PCR时,每次扩增(转录)生成的UMI都不同,也就是身份证号码不同。如何计算UMI数?扩增的时候,Barcode是不会变的,也就是你国籍不会变,但人多了。所以相同Barcode/国籍,但UMI/身份证不同就能进行计数)
- 其他的参数哦那个的比较少,可自行了解
Read10得到的,一般不关注这个:
i是矩阵中非0值的行索引,p是矩阵中非0值的列索引,所以i、p就是非0值的行坐标和列坐标。Dim是矩阵维度。Dimnames就是这个矩阵的行名(基因名)和列名(细胞名),Dimnames[[1]] 包含基因名称,Dimnames[[2]] 包含细胞名称。x是一个稀疏矩阵,里面的就是矩阵里的值。factors包含了与数据矩阵中的列相关的因子或分组信息。这些因子通常表示不同的样本、细胞类型、批次等,在这里就没保存什么信息。
转成的Seurat对象SZDX0224_project:
初步查看Seurat对象SZDX0224_project:
36601个基因,728个细胞
获取细胞数:
ncol(SZDX0224_project)和ncol(SZDX0224)均可
3、计算线粒体基因占比
计算线粒体基因占比的原因:当线粒体的RNA含量过高的时候,可能意味着细胞的细胞核不太活跃,也就是正常的胞质RNA含量下降。就有两种情况:1、细胞活性不太好,需要过滤掉 2、细胞本身线粒体含量比较高。在这里,percent就是这个Barcode里检测到的RNA,有百分之percent的是线粒体的RNA(percent的单位是%)
SZDX0224_project[["percent.mt"]] <- PercentageFeatureSet(SZDX0224_project, pattern = "^MT-")
#### 查看效果 ####
# 以条形图的形式展示线粒体基因的占比与对应的数量
hist(SZDX0224_project[["percent.mt"]]$percent.mt)
# 人源的数据为MT,鼠源的需要换成mt,选取前5个
head(SZDX0224_project@meta.data,5)
# 以小提琴图的形式展示测序的细胞情况
VlnPlot(SZDX0224_project, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3) # ncol是每行展示多少张图
# 以散点图的形式表示
plot1 <- FeatureScatter(SZDX0224_project, feature1 = "nCount_RNA", feature2 = "percent.mt")
plot2 <- FeatureScatter(SZDX0224_project, feature1 = "nCount_RNA", feature2 = "nFeature_RNA")
if(!require(patchwork))install.packages("patchwork")
CombinePlots(plots = list(plot1, plot2))
PercentageFeatureSet函数:
PercentageFeatureSet(object, features = NULL, pattern = NULL, slot = "RNAcounts", subset = NULL)
- object(必需):一个Seurat对象,包含了单细胞RNA测序数据。
- features(可选):一个字符向量,包含要计算百分比的基因名称。如果想知道部分基因的情况,可直接输入features = c("基因名1", "基因名2", "基因名3", "基因名4", "基因名5")
- pattern(可选):一个字符,用于筛选具有匹配模式的基因名称。在这里我们使用了^MT-,这代表人的线粒体基因。一般来说,features和pattern这两个参数选一个就行
经过查找后,SZDX0224_project的meta.data发生了变化:
条形图查看线粒体基因占比:
小提琴图:
散点图:
每个点都是一个细胞,nFeature_RNA指每个细胞中检测到的基因的数目,nCount_RNA是代表的是每个细胞识别到的RNA的数量即UMI(每个基因都会检测到好几条RNA)。对于第一张图,当检测到的RNA数量很少,但线粒体的占比很高(越偏向左上角),说明那个细胞很可能是死亡的。
可以看出我们的细胞质量还是比较好的
4、过滤不合格的数据
SZDX0224_val <- subset(SZDX0224_project, subset = nFeature_RNA > 200 & nFeature_RNA < 7000 & percent.mt < 20)
subset函数:
subset(object, subset, ...)
- object(必需):一个Seurat对象,包含了单细胞RNA测序数据和其他相关信息。
- subset(必需):一个逻辑表达式,用于指定提取细胞子集的条件。只有满足条件的细胞将被包含在子集中。
- ...:其他参数通常不需要使用
可以看到有5个细胞被过滤了出去,4代表着现在meta.data有四个数据
5、标准化
归一化的目的是消除不同样本之间的技术差异和批次效应,以及使得不同细胞之间的表达值在数量级上可比较。
SZDX0224_val <- NormalizeData(SZDX0224_val, normalization.method = "LogNormalize", scale.factor = 10000) # 归一化到10000
SZDX0224_val <- FindVariableFeatures(SZDX0224_val, selection.method = "vst", nGenes = 2000) # 寻找2000个显著变异的基因特征
SZDX0224_val <- ScaleData(SZDX0224_val, vars.to.regress = c("percent.mt")) # vars.to.regress是去除线粒体基因的占比
NormalizDatah函数:
NormalizeData(object, normalization.method = "LogNormalize", scale.factor = 10000, do.scale = TRUE, genes.use = NULL)
- object(必需):一个Seurat对象,包含了原始的单细胞RNA测序数据。
- normalization.method(可选):一个字符,指定归一化方法。常用的方法包括:"LogNormalize"(默认值):对数据进行对数变换,以稳定方差,并将数据缩放到一个常数(默认是 10,000)。 "CLR":进行中心对数比例(Centered Log Ratio)变换。 "SCT":使用SCTransform方法进行归一化。
- scale.factor(可选):一个数值,用于确定归一化后的数据的缩放因子。默认值是 10,000。
- do.scale(可选):一个逻辑值,指示是否对数据进行缩放。如果为TRUE(默认值),则进行缩放。
- genes.use(可选):一个字符向量,包含要用于归一化的基因名称。如果未指定,将对所有基因进行归一化
FindVariableFeatures函数:
FindVariableFeatures(object, selection.method = "vst", nfeatures = NULL, min.mean = 0.0125, max.mean = 3, min.disp = 0.5)
- object(必需):一个Seurat对象,包含了原始的单细胞RNA测序数据。
- selection.method(可选):一个字符,指定用于选择变异特征的方法。常用的方法包括:"vst"(默认值):使用Variance Stabilizing Transformation(VST)方法。 "dispersion":使用基于离散度的方法。 "mean.var.plot":使用平均方差图。
- nfeatures(可选)/和nGene是等效的:一个整数,指定要选择的变异特征的数量。如果未指定,函数将选择符合其他条件的特征。
- 其他参数一般默认值即可
ScaleData函数:
ScaleData(object, features = NULL, vars.to.regress = NULL, model.use = "vars.to.regress", do.scale = TRUE, do.center = TRUE, block.size = 2000)
- object(必需):一个Seurat对象,包含了原始的单细胞RNA测序数据。
- vars.to.regress(可选):一个字符向量,包含要在标准化中移除的技术变量的名称。这些变量通常表示不感兴趣的技术效应,如细胞计数或批次效应。
- 其他参数一般默认值即可
标准化后的SZDX0224_val:
6、PCA降维/线性降维/主成分分析
一般是直接分析高变基因
SZDX0224_val <- RunPCA(SZDX0224_val, features = VariableFeatures(object = SZDX0224_val)) # 线性降维
# 以点图的形式展示前两个维度 意义不大
VizDimLoadings(SZDX0224_val, dims = 1:2, reduction = "pca")
# 获得主成分的散点图,根据此图可选取需要多少个主成分进行降维
ElbowPlot(SZDX0224_val, ndims = 50) # 根据这里的图,可以看到大概选取15个主成分就够了
# 热图形式判断选哪些主成分 这个意义不大
DimHeatmap(SZDX0224_val, dims = 1:20, cells = 500, balanced = T)
# 同样是用于选取主成分
SZDX0224_val <- JackStraw(SZDX0224_val, num.replicate = 100)
SZDX0224_val <- ScoreJackStraw(SZDX0224_val, dims = 1:20)
JackStrawPlot(SZDX0224_val, dims = 1:20)
RunPCA函数:
RunPCA(object, features = NULL, npcs = 50, ndims.print = 10, subset.row = NULL, do.print = FALSE, pcs.print = 1:5, seed.use = NULL)
- object(必需):一个Seurat对象,包含了单细胞RNA测序数据。
- features(可选):一个字符向量,包含要用于PCA分析的特征(通常是基因)的名称。如果未指定,将对所有特征进行PCA分析。
- 其他参数默认即可
散点图:
这里得到的是每个主成分的里,基因之间的差异,一般选择主成分的方式就看哪个点开始变平滑。
7、非线性降维+聚类
SZDX0224_val <- FindNeighbors(SZDX0224_val, dims = 1:15)
SZDX0224_val <- FindClusters(SZDX0224_val, resolution = 0.6) # 想聚类分得更细(分群分的更细),可以换更大的值,比如1.2等,一般先分一个粗一点的分群
SZDX0224_val <- RunUMAP(SZDX0224_val, dims = 1:15) # 非线性降维
SZDX0224_val <- RunTSNE(SZDX0224_val, dims = 1:15)
#### 查看聚类效果
DimPlot(SZDX0224_val, reduction = "umap", label = T)
DimPlot(SZDX0224_val, reduction = "tsne", label = T)
这里就不详细解释每个函数了,基本就使用这几个参数,其他保持默认。
tsne图:
之后SZDX0224_val的结果:
8、去除多包液滴
不可避免会出现多包的情况,这里用DoubletFinder去除
具体怎么个去除法。。。不是很懂,只知道这样就能去除多包的细胞
devtools::install_github('chris-mcginnis-ucsf/DoubletFinder')
library(DoubletFinder)
saveRDS(SZDX0224_val, file = "./Data/SZDX-0224_outs/SZDX0224.rds")
readRDS(SZDX0224_val, file = "./Data/SZDX-0224_outs/SZDX0224_val.rds")
SZDX0224_val_db <- SZDX0224_val
# 寻找最优pK值
sweep.res.list_SZDX0224_val <- paramSweep_v3(SZDX0224_val_db,PCs = 1:30, sct = F)
sweep.stats_SZDX0224_val <- summarizeSweep(sweep.res.list_SZDX0224_val, GT = F)
bcmvn_SZDX0224_val <- find.pK(sweep.stats_SZDX0224_val)
pK_value<-as.numeric(as.vector(bcmvn_SZDX0224_val$pK[which.max(bcmvn_SZDX0224_val$BCmetric)])) # 最佳pK值
# 双细胞比例计算
annotations <- SZDX0224_val@meta.data$seurat_clusters
homotypic.prop <- modelHomotypic(annotations) # 同类细胞的比例
DoubletRate <- 0.004 # 查表
nExp_poi <-round(DoubletRate*length(SZDX0224_val$seurat_clusters)) # 最好提供celltype,而不是seurat_clusters。
nExp_poi.adj <- round(nExp_poi*(1-homotypic.prop)) # 矫正
# 设置pN和pANN_value(这个一般是F)
pN_value <- 0.25
pANN_value <- paste0("pANN_", pN_value, "_", pK_value, "_", nExp_poi)
# 两种方法计算多包,看哪种效果好就行,一般是第二个
# SZDX0224_val_db <- doubletFinder_v3(SZDX0224_val, PCs = 1:30, pN = pN_value, pK = pK_value, nExp = nExp_poi, reuse.pANN = F)
SZDX0224_val_db <- doubletFinder_v3(SZDX0224_val, PCs = 1:30, pN = pN_value, pK = pK_value, nExp = nExp_poi.adj, reuse.pANN = F)
SZDX0224_val_db@meta.data[1:5, ]
SZDX0224_val$doublets <- SZDX0224_val_db$DF.classifications_0.25_0.29_3 # 根据上面那行代码的结果的最后一列,严谨点就是前一列
#### 绘制tsne查看效果
DimPlot(SZDX0224_val, reduction = "tsne", group.by = "doublets")
DimPlot(SZDX0224_val, reduction = "tsne", group.by = "seurat_clusters", label = T)
里面的多包率DoubletRate根据以下表来查(这里是10x的):
挑出来的多包细胞:
9、高表达或特异表达基因
SZDX0224.markers <- FindAllMarkers(SZDX0224_val, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
# 保存marker
write.csv(SZDX0224.markers, './Data/SZDX-0224_outs/SZDX0224.markers.csv')
# 获取每个分群的高表达的基因里前两个基因的数据(包括基因名称等)
SZDX0224.markers %>% group_by(cluster) %>% top_n(n = 2, wt = avg_log2FC)
# 在知道样本的情况下,即知道有哪些群(哪些细胞),根据它有的基因,查看它在哪个群
# 以下都是以下高表达基因在每个群的效果图
# features就是你知道的某个细胞的所拥有的基因
# tsne图展示
FeaturePlot(SZDX0224_val, features = c("HIST2H2AC", "HIST1H3B", "NEAT1", "MIR924HG", "BCLAF1", "HIST1H2BO", "MT-CO1", "MT-ND5"), reduction = "tsne", label = T)
# 小提琴图的形式展示某基因在这个样本里的分群情况(小提琴图的形式看它在哪个群)
VlnPlot(SZDX0224_val, features = c("HIST2H2AC", "HIST1H3B", "NEAT1", "MIR924HG", "BCLAF1", "HIST1H2BO", "MT-CO1", "MT-ND5"), pt.size = 0)
# 以热图的形式展示每个分群的高表达基因里前 10 的的基因的表达情况
top10 <- SZDX0224.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_log2FC)
DoHeatmap(SZDX0224_val, features = top10$gene, label = F, slot = "scale.data")
FindAllMarkers函数:only.pos = TRUE表示只显示高表达的基因,min.pct = 0.25表示在细胞中的比例最少为25%,logfc.threshold = 0.25差异表达基因的最小对数折叠变化(log-fold change)。
以下是每个分群里的高表达基因
以下是各个高变基因的tsne图,颜色越深,表示表达程度越高
# 如果想要某个分群与其他某个分群对比,可按照以下代码运行
marker <- FindMarkers(SZDX0224_val, ident.1 = "0", ident.2 = "1", only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
在这里ident.1 = "0"和ident.2 = "1"表示0群和1群。其他的和FindAllMarkers函数一样。
p_val用于衡量基因的差异表达程度,越小表示在不同的细胞群之间的表达差异越显著。p_val_adj则是经过校正后的p_val。一般用p_val_adj。
pct.1和pct.2分别是基因在对应分群的表达率。
10、细胞类型标注(就是将原来的数字改为对应的细胞名)
new.cluster.ids <- c("细胞名0", "细胞名1", "细胞名2", "细胞名3") # 细胞类型标注向量
names(new.cluster.ids) <- levels(SZDX0224_val) # 将创建的新细胞簇名称列表的每个元素与原始数据中的细胞簇名称(0、1、2、3)相匹配
SZDX0224_val <- RenameIdents(SZDX0224_val, new.cluster.ids) # 更改细胞类型标注
DimPlot(SZDX0224_val, reduction = "tsne", label = T)
table(Idents(SZDX0224_val)) # 查看有多少个细胞
SZDX0224_val@meta.data[1:5, ]
SZDX0224_val$cell_cluster_origin <- Idents(SZDX0224_val)
SZDX0224_val@meta.data[1:5, ]
saveRDS(SZDX0224_val, file = "./Data/SZDX-0224_outs/SZDX0224_val.rds")