单细胞数据的导入与质控 - Seurat
######################################
- 题目:单细胞数据的导入与质控 - Seurat
- 语言:R
- Author: YQ
######################################
step0.设置工作环境
-
方法一:新建repository,在该repo内写R.scripts
-
方法二:setwd()
setwd('/Users/apple/Desktop/Rsave/')
getwd()
创建以下目录
single_cell_rnaseq/
├── data
├── results
└── figures
step1.导入数据,创建计数矩阵
目前我碰到的有这几种情况;
- 情况一:三个文件
三个文件指的是“barcodes.tsv","features.tsv","matrix.mtx";
这个情况就比较好处理了,barcodes.tsv就是cell id,features.tsv就是gene id,matrix.mtx就是计数counts矩阵
##示例 https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE136916
# 设置默认路径
matrix_dir = '/Users/apple/Desktop/Rwork/Glasslung/'
# 按路径读取三个文件
barcode.path<-paste0(matrix_dir,"barcodes.tsv")
genes.path<-paste0(matrix_dir,"features.tsv")
matrix.path<-paste0(matrix_dir,"matrix.mtx")
# readMM读取数据的values,columns,index
zebrafish.data <- readMM(file = matrix.path) ##mac上不能读压缩文件
gene.names = read.delim(genes.path,header = FALSE, stringsAsFactors = FALSE)
barcode.names = read.delim(barcode.path,header = FALSE,stringsAsFactors = FALSE)
colnames(zebrafish.data) = barcode.names$V1
rownames(zebrafish.data) = gene.names$V2 ##把示例中的V1改成V2
# check矩阵
zebrafish.data[1:6, 1:6] ##check矩阵
dim(zebrafish.data) ##check矩阵
- 情况二:直接给了计数矩阵的csv
单个csv矩阵读入
# 读取csv格式的矩阵
data1 <- read.csv("/Users/quyue/Desktop/gene_bc_matrices.csv", header = T, row.names = 1)
# csv矩阵转换成数据框
datan = data.frame(data1)
# 数据框转换成稀疏矩阵matrix
dataan <- as(as.matrix(datan), "dgCMatrix")
多个csv矩阵读入
# 设置默认路径
matrix_dir = '/Users/quyue/Desktop/bioinfo/bonemarrowniche/0526data/' # 为了避免重复输入默认路径,赋值给matrix_dir
# 读取多个csv
data1 <- read.csv(paste0(matrix_dir, "GSM3714747_chow1_filtered_gene_bc_matrices.csv"), header = T,row.names= 1)
data2 <- read.csv(paste0(matrix_dir, "GSM3714748_chow2_filtered_gene_bc_matrices.csv"), header = T,row.names= 1)
data3 <- read.csv(paste0(matrix_dir, "GSM3714749_chow3_filtered_gene_bc_matrices.csv"), header = T,row.names= 1)
# csv合并成数据框
datan = data.frame(data1,data2,data3)
# 数据框转换成稀疏矩阵matrix
dataan <- as(as.matrix(datan), "dgCMatrix")
- 情况三:直接给了计数矩阵的txt
单个txt矩阵读入
# 读取txt格式的矩阵
data1 <- read.table("/Users/quyue/Desktop/GSM2915579_5FU-cntrl-col23.txt", header = T, row.names = 1)
# txt矩阵转换成数据框
datan = data.frame(data1)
# 数据框装转换成稀疏矩阵matrix
dataan <- as(as.matrix(datan),"dgCMatrix")
多个txt矩阵读入
# 设置默认路径
matrix_dir = "/Users/quyue/Desktop/"
# 读取多个txt格式的矩阵
data1 = read.table(paste0(matrix_dir,"GSM2915579_5FU-cntrl-col23-1.txt"), header = T, row.names = 1)
data2 = read.table(paste0(matrix_dir,"GSM2915579_5FU-cntrl-col23-2.txt"), header = T, row.names = 1)
data3 = read.table(paste0(matrix_dir,"GSM2915579_5FU-cntrl-col23-3.txt"), header = T, row.names = 1)
dataa = cbind(data1, data2, data3) #行数不同,会生成NaN值
# txt矩阵转换成数据框
datan = data.frame(dataa)
# 数据框转换成稀疏矩阵matrix
dataan <- as(as.matrix(datan),"dgCMatrix") # 此步骤是否必要有待验证
- 情况四:xslx文件
其实就是用R读取excel文件,把xslx转化成csv再读取
# 加载openxslx这个R包
library('openxslx')
# 读入xslx格式矩阵
a <- read.xslx("test.xslx",sheet = 1) # 文件名+sheet序号
# 把xslx格式矩阵转换成csv格式矩阵
# 获取excel中工作簿的名称
sheetnames<-getSheetNames('test.xlsx')
#把每个工作薄的数据按照'工作薄名称.csv'的名称存储
for(iin(1:length(sheetnames))){
write.table(read.xlsx('/Users/quyue/Desktop/test.xlsx',sheet=i),paste(sheetnames[i],'.csv',sep=''),row.names=F,sep=',')
} # 有待验证,不是我自己写的
# 读取csv格式矩阵
data1 <- read.csv("/Users/quyue/Desktop/test.csv", header = T, row.names = 1)
# 把csv格式矩阵转换成数据框
datan = data.frame(data1)
# 把数据框转换成稀疏矩阵matrix
dataan <- as(as.matrix(datan), "dgCMatrix")
- 情况五:直接给了已经构建好seurat对象的R.data
# 直接load R.data
load(file = "/Users/quyue/Desktop/bioinfo/bonemarrowniche/RNAMagnetDataBundle/NicheData10x.rda")
> Loading required package: Seurat
# load完以后,看到底是什么数据类型,并查看数据
NicheData10x
> An object of class Seurat # 已经是seurat对象了
16701 features across 7497 samples within 1 assay
Active assay: RNA (16701 features, 2872 variable features)
2 dimensional reductions calculated: pca, tsne
View(NicheData10x) # 显示seurat的具体参数
step2.构建矩阵为seurat对象
找到一个解释Seurat中所有函数的网站,比R自带的要清楚很多 rdrr
工作流程
-
generation of the count matrix 生成计数矩阵
格式化读取、分离样本、映射(mapping)、定量(quantification); -
quality control of the raw counts 原始矩阵质量控制
过滤掉质量差的细胞 -
clustering of filtering counts 过滤后计数的聚类
将转录活动相似的细胞归为一类(细胞类型=不同的聚类) -
Marker identification 标记识别
识别每个细胞群的基因标记(marker) -
Optional downstream steps 其他可选的下游步骤
2.1 稀疏矩阵到seurat对象
2.1.1 使用ReadMM()或者Read10x()读取单个样本数据
- 函数用法说明:
1.readMM():
input:"xx.mtx"
备注:readMM is the function of Matrix packages, it changes the standard matrix into sparse matrix.Of note,features.tsv and barcodes.tsv should be library first, and then combine sparse matrix、features.tsv and barcodes.tsv form a counts matrix with cell id and gene id.(详见step1情况一)
2.read10X():
input:"raw_feature_bc_matrix"(files from CellRanger output)
备注:read10X id the function of Seurat,its input from CellRanger output(10X genomics data的专用软件Cell Ranger的output会有一个out目录,"raw_feature_bc_matrix"在该目录中)
library(Seurat)
# 按1中方法完成数据读入到稀疏矩阵输出的过程
# sparse matrix稀疏矩阵
ctrl_counts <- Read10x(data.dir = "data/ctrl_raw_feature_bc_matrix")
# 将稀疏矩阵转换成一个Seurat
ctrl <- CreateSeuratObject(counts = ctrl_counts,
min.features = 100)
# 查看Seurat对象的元数据
head(ctrl@meta.data)
## 备注:元数据 meta.data代表什么?
orig.ident # 通常包含所知的样品名字,默认为“SeuratProject”
nCount_RNA # 每个细胞的UMI数目
nFeature_RNA # 每个细胞所检测到的基因数目
2.1.2 使用for循环读入多个样本数据
- R中for 循环的语法结构
for (variable in input){
command1
command2
command3
}
- R中for循环实现读入多个样本数据
## 目的:for loop iterate 两个样本的文件
## 思路:执行三个命令 (1) 使用Read10x()读取计数数据;(2)使用CreateSeuratObject()从读取的数据中创建Seurat对象;(3)根据样本名将Seurat对象赋值给一个新的变量(好处是不会覆盖上一次迭代中创建的Seurat对象)
mtx_dir = "/Users/quyue/Desktop/"
for (files in c("ctrl_raw_feature_bc_matrix","stim_raw_feature_bc_matrix")){
seurat_data <- Read10X(data.dir = paste0(mtx_dir, file)) # (1)
seurat_obj <- CreateSeuratObject(counts = seurat_data,
min.features = 100,
project = file) #(2)
assign(file, seurat_obj) #(3)
}
2.2 查看seurat对象元数据&merge
再完成2.1已经创建好了Seurat对象以后,快速查看元数据以了解其大概;
## 查看新Seurat对象的元数据
head(ctrl_raw_feature_bc_matrix@meta.data)
head(stim_raw_feature_bc_matrix@meta.data)
接着,需要把多个seurat对象合并成一个,这样比较方便我们同时为每个样品进行质控,且方便我们更容易地比较所有样本的数据质量,用merge()函数执行该操作;
## 创建一个合并的Seurat对象
## 用add.cell.id参数将样品特异的前缀添加到每个细胞ID,用以区分不同样本中的同个细胞ID
merged_seurat <- merge(x = ctrl_raw_feature_bc_matrix,
y = stim_raw_feature_bc_matrix,
add.cell.id = c("ctrl","stim"))
## 查看合并对象是否有对应的样本前缀
head(merged_seurat@meta.data)
tail(merged_seurat@meta.data)
step3. 进行质控流程(QC and pre-processing)
3.1 熟悉质控指标
通常根据以下四个指标筛选:
# 每个细胞的read counts数目(UMI指的是molecular ID)
nCount_RNA # (> 1000)
# 每个细胞所检测到的基因数目
nFeature_RNA # (> 1000)
# 线粒体基因比例 mitoRatio
mitoRatio # (< 5%)
# 单位UMI(read count=molecular id)检测到的gene数目的比例(这个数据让我们知道数据的复杂性)
GenesPerUMI
3.2 标准的质控分析流程 - Standard pre-processing workflow
3.2.1 计算质控指标
- 需要计算的主要是mitoRatio和GenesPerUMI(因为nCount_RNA和nFeature_RNA在meta.data中)
1.计算mitoRatio
主要是利用的Seurat的PercentageFeatureSet()功能,这个函数将使用一个模式(pattern)搜索基因标识符,对于每一列(细胞),它将选取特征基因的计数之和,除以所有基因的计数之和
## count mitoRatio with PercentageFeatureSet() 并添加 mito Ratio这一项到 meta.data当中
# 方法一
## The [[ operator can add columns to object metadata. This is a great place to stash QC stats
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
# 方法二
pbmc$mitoRatio <- PercentageFeatureSet(object = pbmc, pattern = "^MT-")
pbmc$mitoRatio <- pbmc@meta.data$mitoRatio / 100
2.计算log10GenesPerUMI(option)
GenesPerUMI = nFeature_RNA / nCount_RNA
这个指标代表的意思是 “单位read counts的gene数目的比例” 反映的是数据的复杂度;常用于评估ctrl和stim基因的整体复杂性
## count log10GenesPerUMI and add it to seurat object metadata
pbmc$log10GenesPerUMI <- log10(pbmc$nFeature_RNA)/log10(pbmc$nCount_RNA)
3.2.2 可视化质控指标
## 一般可视化以下三个参数即可:"nFeature_RNA", "nCount_RNA", "percent.mt"
VlnPlot(pbmc, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3, pt.size=0.05)
## 可视化log10GenesPerUMI(option)
# 通过可视化每一个UMI检测到的基因数来可视化基因表达的整体复杂性
metadata %>%
ggplot(aes(x=log10GenesPerUMI, color = sample, fill=sample)) +
geom_density(alpha = 0.2) +
theme_classic() +
geom_vline(xintercept = 0.8)
3.2.3 筛选 Filtering(option - 因为一般给的是经过筛选过后的gene mtx)
3.2.3.1 细胞水平的筛选(Cell-level filtering)
- 参考阈值
nUMI > 500
nGene > 250
log10GenesPerUMI > 0.8
mitoRatio < 0.2
细胞水平的过滤, 主要是用subset()函数过滤
# 使用选择的阈值筛掉低质量读写 - 这些将会随实验而改变
filtered_pbmc <- subset(x = pbmc, subset= (nUMI >= 500) &
(nGene >= 250) &
(log10GenesPerUMI > 0.80) &
(mitoRatio < 0.20))
3.2.3.2 基因水平的筛选(Gene-level filtering)
在我们的数据中,会有许多基因的计数为零。这些基因会显著降低一个细胞的平均表达量,因此我们将从数据中删除它们。
主要删除两类基因,
(1)删除所有细胞中零表达的基因;
(2)如果一个基因只在少数几个细胞中表达,那么它的意义并不是特别大,因为它仍然会把没有表达它的其他所有细胞的平均表达量降下来。对于我们的数据,我们选择只保留在10个或更多细胞中表达的基因。
# 提取计数
counts <- GetAssayData(object = filtered_pbmc, slot = "counts")
# 根据在每个细胞的计数是否大于0为每个基因输出一个逻辑向量
nonzero <- counts > 0
# 将所有TRUE值相加,如果每个基因的TRUE值超过10个,则返回TRUE。
keep_genes <- Matrix::rowSums(nonzero) >= 10
# 仅保留那些在10个以上细胞中表达的基因
filtered_counts <- counts[keep_genes, ]
# 重新赋值给经过过滤的Seurat对象
filtered_pbmc <- CreateSeuratObject(filtered_counts, meta.data = filtered_pbmc@meta.data)
3.2.4 重新评估质量指标 (Re-assess QC metrics)
在进行过滤后,建议回过头来再看看指标,确保你的数据符合你的预期,对下游分析有好处。
3.2.5 保存筛选过的细胞 (Saving filtered cells)
我们将保存筛选后的细胞对象用于聚类 (clustering) 和标记识别 (marker identification),将过滤以后的Seurat数据创建为.RData对象
# 创建.RData对象以方便在任何时候导入
save(filtered_pbmc, file="data/pbmc_seurat_filtered.RData")