单细胞GSEA分析需要的文件有两个:
1. 单细胞基因表达变化数据(两列,一列是geneid/gene symbol,一列是logFC)(文件格式:.rnk)
2. 目标基因集(文件格式:.gmx或.gmt)一行是一个term/基因集,第一列是基因集的名称,后面是基因分类等,再后面是geneid/gene symbol(要和单细胞矩阵的对应,否则不能识别)
1. 单细胞基因表达变化数据的准备
- 1.1 下载单细胞数据(pbmc5k)
wget http://cf.10xgenomics.com/samples/cell-exp/3.0.2/5k_pbmc_v3/5k_pbmc_v3_filtered_feature_bc_matrix.tar.gz
tar xvzf 5k_pbmc_v3_filtered_feature_bc_matrix.tar.gz
- 1.2 参考Seurat标准流程对数据进行预处理得到分群
library(tidyverse)
library(Seurat)
# Load the PBMC dataset
pbmc.data <- Read10X(data.dir = "filtered_feature_bc_matrix/")
# Initialize the Seurat object with the raw (non-normalized data).
pbmc <- CreateSeuratObject(counts = pbmc.data, project = "pbmc5k", min.cells = 3, min.features = 200)
#质控
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
#取子集
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 5000 & percent.mt < 25)
#标准化和归一化
pbmc <- NormalizeData(pbmc, normalization.method = "LogNormalize", scale.factor = 10000)
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)
all.genes <- rownames(pbmc)
pbmc <- ScaleData(pbmc, vars.to.regress = "percent.mt")
#PCA
pbmc <- RunPCA(pbmc, features = VariableFeatures(object = pbmc), verbose = FALSE)
#聚类
pbmc <- FindNeighbors(pbmc, dims = 1:20)
pbmc <- FindClusters(pbmc, resolution = 0.5)
#TSNE和UMAP降维
pbmc <- RunUMAP(pbmc, dims = 1:20)
pbmc<- RunTSNE(pbmc, dims = 1:20)
DimPlot(pbmc, reduction = "umap", label = TRUE)
#查找marker基因
pbmc.markers <- FindAllMarkers(pbmc, only.pos = TRUE, min.pct = 0.25, logfc.threshold = 0.25)
saveRDS(pbmc, "pbmc_5k_v3.rds")
分为13个亚群
- 1.3 使用wilcoxauc()计算每个cluster的差异基因
pbmc<- readRDS("pbmc_5k_v3.rds")
library(presto)
pbmc.genes <- wilcoxauc(pbmc, 'seurat_clusters')
head(pbmc.genes)
# feature group avgExpr logFC statistic auc
# 1 AL627309.1 0 0.004801016 -0.0048337160 2113594 0.4966881
# 2 AL627309.3 0 0.000000000 -0.0004923881 2126401 0.4996978
# 3 AL669831.5 0 0.058225088 -0.0101451241 2081447 0.4891337
# 4 FAM87B 0 0.000000000 -0.0017590952 2121900 0.4986401
# 5 LINC00115 0 0.033568380 -0.0054911605 2090280 0.4912094
# 6 FAM41C 0 0.015927696 -0.0162813395 2077756 0.4882664
# pval padj pct_in pct_out
# 1 0.0451711892 0.0817186691 0.5443235 1.20882442
# 2 0.3781096732 0.4754137751 0.0000000 0.06044122
# 3 0.0182067030 0.0364774662 6.8429238 9.21728619
# 4 0.0612494406 0.1063124181 0.0000000 0.27198549
# 5 0.0148011270 0.0301102065 3.7325039 5.59081293
# 6 0.0001622764 0.0004571717 2.0217729 4.38198852
dplyr::count(pbmc.genes, group)# 查看每个cluster中有多少基因(与矩阵的基因数一致)
# group n
# 1 0 18791
# 2 1 18791
# 3 10 18791
# 4 11 18791
# 5 12 18791
# 6 2 18791
# 7 3 18791
# 8 4 18791
# 9 5 18791
# 10 6 18791
# 11 7 18791
# 12 8 18791
# 13 9 18791
- 1.4 选取group0的差异基因进行GSEA分析,将cluster0的 差异基因整理为GSEA分析需要的数据格式(也可输入注释好的细胞群的差异基因)
# 仅选择fgsea的feature和auc列
cluster0.genes<- pbmc.genes %>% dplyr::filter(group == "0") %>% arrange(desc(auc)) %>% dplyr::select(feature, auc)
ranks<- deframe(cluster0.genes)
head(ranks)
# RPL30 RPS3A RPS13 RPL35A RPL32 RPL34
# 0.9376551 0.9358956 0.9250745 0.9196189 0.9185743 0.9132980
2. 选择自己数据的物种以及要做的GSEA的数据库类型,准备目标基因集的输入文件
为了进行基因集富集分析,首先需要注释基因集。一个重要的来源是Broad Institute开发的MsigDB。
网址:https://www.gsea-msigdb.org/gsea/msigdb/
library(msigdbr)
library(fgsea)
library(dplyr)
library(ggplot2)
##查看物种的数据 msigdbr_show_species();#我们使用C7免疫基因集
m_df<- msigdbr(species = "Homo sapiens", category = "C7")
head(m_df)
##将m_df的基因与通路取出并改成一个通路对应相应基因的格式
fgsea_sets<- m_df %>% split(x = .$gene_symbol, f = .$gs_name)
#以gs_name为factor对gene_symbol进行分类,统计落在每个gs_name中的gene_symbol的个数,并生成list。
summary(fgsea_sets)
3. 使用fgsea进行基因集富集并绘图
- 3.1 富集分析
fgseaRes<- fgsea(fgsea_sets, stats = ranks, nperm = 1000)
#nperm设置的是permutation次数
- 3.2 整理数据:
fgseaResTidy <- fgseaRes %>% as_tibble() %>% arrange(desc(NES))
fgseaResTidy %>% dplyr::select(-leadingEdge, -ES, -nMoreExtreme) %>% arrange(padj) %>% head()
- 3.3 绘图
应用标准化富集分数绘制barplot
# 显示top20信号通路
ggplot(fgseaResTidy %>% filter(padj < 0.008) %>% head(n= 20), aes(reorder(pathway, NES), NES)) +
geom_col(aes(fill= NES < 7.5)) +
coord_flip() +
labs(x="Pathway", y="Normalized Enrichment Score",
title="Hallmark pathways NES from GSEA") +
theme_minimal() ####以7.5进行绘图填色
GSEA图
plotEnrichment(fgsea_sets[["GSE10325_CD4_TCELL_VS_MYELOID_UP"]],
ranks) + labs(title="GSE10325 CD4 TCELL VS MYELOID UP")
上图中,最上面的绿线是遍历排好序的基因列表以计算ES值的过程。遍历基因集中的基因时,当基因出现在目标基因(横轴的基因)中则加分,反之减分。加减分值由基因与表型的相关性决定。当分值积累到最大就是富集分数。
X轴是实验中的所有基因(在这里大约为20,000)。每个黑条是该基因集中的基因(途径),我们可以知道基因在排序列表中的位置。
如果基因集位于预先排列的基因列表的顶部,则通过某种度量计算出富集分数(enrichment score,ES),ES为正。如果基因集位于预先排列的基因列表的底部,则ES为负。
从以上图中可以看出多数基因都落在了峰值之前(绿线峰值)的核心基因集中,表明基因在该数据集中的显著富集,也就是高表达。
4. 常规GSEA分析
GSEA(软件)分析需要准备的文件:
- 基因表达量表(.gct / .txt)文件
- 样本分类关系表(.cls)文件
- 基因集合(.gmt)文件
- 4.1 基因表达量表文件
新建excel,将数据整理成下面的格式,存储为.txt文件。
- 4.2 样本分类关系表(.cls)文件
新建excel
第一行分别是:样本数、几个分组、1(固定不需要改)
第二行分别是:#、分组1、分组2
第三行是每个组的样本,0代表CON组,1代表CASE组
将文件保存成.txt格式,随后更改后缀为.cls (一定要先保存成.txt格式,若先存成.xlsx格式再改成.cls,读入GSEA软件会报错)
- 4.3 基因集合(.gmt)文件
人的文件可以直接从GSEA官网上下载
小鼠的文件(以KEGG上下载的数据集做演示):
首先,在KEGG数据库中下载小鼠的KEGG通路数据库文件
这样就得到了下载.keg文件
先在Linux下解析keg文件
#解析信息
perl -alne '{if(/^C/){/PATH:mmu(\d+)/;$kegg=$1}else{print "$kegg\t$F[1]" if /^D/ and $kegg;}}' mmu00001.keg > mmu00001_kegg2gene.txt
grep '^C' mmu00001.keg | grep "mmu" | sed 's/^C //g' | sed 's/\([0-9]*\)\s/\1\t/' > mmu00001_kegg2description.txt
再用R制作.gmt文件
#转换ID同时制作.gmt文件
#安装转换ID需要用到的各个R包
install.packages("data.table")
BiocManager::install("org.Mm.eg.db")
BiocManager::install("clusterProfiler")
#调用各个R包
library(data.table)
library(org.Mm.eg.db)
library(clusterProfiler)
#读入数据
path2gene_file<-"mmu00001_kegg2gene.txt"
tmp=read.table(path2gene_file,sep="\t",colClasses=c('character'))
dt <- tmp
dt$geneid <- rownames(dt)
# transform id
map_dt <- bitr(dt$V2, fromType = "ENTREZID",toType = c( "SYMBOL"),OrgDb = org.Mm.eg.db)
dt_merge <- merge(map_dt,dt, by.y = "V2", by.x = "ENTREZID")
# 可以把转换ID后的表输出
#write.table(dt_merge, file = "example42.txt", sep = "\t", col.names = T, row.names = T, quote = F)
# first column is kegg ID, second column is entrez ID
GeneID2kegg_list<- tapply(tmp[,1],as.factor(tmp[,2]),function(x) x)
kegg2symbol_list<- tapply(dt_merge$SYMBOL,as.factor(dt_merge$V1),function(x) x)
View(kegg2symbol_list)
#输出数据,但描述列为NA
write.gmt <- function(geneSet=kegg2symbol_list,gmt_file='kegg2symbol.gmt'){
sink( gmt_file )
for (i in 1:length(geneSet)){
cat(names(geneSet)[i])
cat('\tNA\t')
cat(paste(geneSet[[i]],collapse = '\t'))
cat('\n')
}
sink()
}
write.gmt()
在上面的gmt文件里添加自定义基因集:
gene50 <- matrix$mygene[1:50]
GeneID2kegg_list$gene50 <- gene50
然后重复上面的输出gmt文件。如果只想要自定义基因集,可以在加入自定义基因集后删掉其他基因集。
- 4.4 排序文件
前面我们得到了GSEA软件需要用的三个文件,但GSEA软件的图默认是.png,且不够清晰。如果想使用R画图,除了需要上面的.gmt文件还需要排序文件
rm(list = ls())
options(stringsAsFactors = F)
# library(org.Hs.eg.db)
library(org.Mm.eg.db)
library(clusterProfiler)
library(enrichplot)
library(tidyverse)
library(ggstatsplot)
#读入差异分析结果
DEG_DESeq2_all <- read_excel("DEG_DESeq2_all.xlsx")
## 物种设置
organism = 'hsa' # 人类'hsa' 小鼠'mmu'
OrgDb = 'org.Hs.eg.db'#人类"org.Hs.eg.db" 小鼠"org.Mm.eg.db"
#### 按照需要可选择不同的DEG方法数据集 ####
need_DEG <- DEG_DESeq2_all
need_DEG <- need_DEG[,c(2,4,7)] #选择SYMBOL, log2FoldChange和pvalue(凑成数据框)
colnames(need_DEG) <- c('SYMBOL','log2FoldChange','pvalue')
##### 创建gsea分析的geneList(包含从大到小排列的log2FoldChange和ENTREZID信息)####
#转化id
df <- bitr(need_DEG$SYMBOL, fromType = "SYMBOL",toType = "ENTREZID", OrgDb = 'org.Hs.eg.db') #人数据库org.Hs.eg.db 小鼠org.Mm.eg.db
need_DEG <- merge(need_DEG, df, by='SYMBOL') #按照SYMBOL合并注释信息
need_DEG <- filter(need_DEG,need_DEG$log2FoldChange!='Inf')
need_DEG <- filter(need_DEG,need_DEG$log2FoldChange!='=Inf')
geneList <- need_DEG$log2FoldChange
#geneList <- as.numeric(geneList)
names(geneList) <- need_DEG$ENTREZID
geneList <- sort(geneList, decreasing = T) #从大到小排序
这样得到的是以ENTREZID命名的"numeric",接下来就可以进行常规GSEA分析
##### gsea富集 ####
KEGG_kk_entrez <- gseKEGG(geneList = geneList,
organism = 'mmu', #人hsa 鼠mmu
pvalueCutoff = 0.25) #实际为padj阈值,可调整
KEGG_kk <- DOSE::setReadable(KEGG_kk_entrez,
OrgDb=OrgDb,
keyType='ENTREZID')#转化id
GO_kk_entrez <- gseGO(geneList = geneList,
ont = "ALL", # "BP"、"MF"和"CC"或"ALL"
OrgDb = 'org.Mm.eg.db',#人类org.Hs.eg.db 鼠org.Mm.eg.db
keyType = "ENTREZID",
pvalueCutoff = 0.25) #实际为padj阈值可调整
GO_kk <- DOSE::setReadable(GO_kk_entrez,
OrgDb=OrgDb,
keyType='ENTREZID')#转化id
#save(KEGG_kk_entrez, GO_kk_entrez, file = "GSEA_result.RData")
###可视化
##选取富集结果
kk_gse <- KEGG_kk
kk_gse_entrez <- KEGG_kk_entrez
###条件筛选
#一般认为|NES|>1,NOM pvalue<0.05,FDR(padj)<0.25的通路是显著富集的
kk_gse_cut <- kk_gse[kk_gse$pvalue<0.05 & kk_gse$p.adjust<0.25 & abs(kk_gse$NES)>1]
kk_gse_cut_down <- kk_gse_cut[kk_gse_cut$NES < 0,]
kk_gse_cut_up <- kk_gse_cut[kk_gse_cut$NES > 0,]
#选择展现NES前几个通路
down_gsea <- kk_gse_cut_down[tail(order(kk_gse_cut_down$NES,decreasing = T),10),]
up_gsea <- kk_gse_cut_up[head(order(kk_gse_cut_up$NES,decreasing = T),10),]
diff_gsea <- kk_gse_cut[head(order(abs(kk_gse_cut$NES),decreasing = T),10),]
#### 经典的GSEA图
up_gsea$Description
i=2
gseap1 <- gseaplot2(kk_gse,
up_gsea$ID[i],#富集的ID编号
title = up_gsea$Description[i],#标题
color = "red", #GSEA线条颜色
base_size = 20,#基础字体大小
rel_heights = c(1.5, 0.5, 1),#副图的相对高度
subplots = 1:3, #要显示哪些副图 如subplots=c(1,3) #只要第一和第三个图
ES_geom = "line", #enrichment score用线还是用点"dot"
pvalue_table = T) #显示pvalue等信息
gseap1
ggsave(gseap1, filename = 'GSEA_up_1.pdf', width =10, height =8)
#### 合并 GSEA通路
gseap2 <- gseaplot2(kk_gse,
up_gsea$ID,#富集的ID编号
title = "UP_GSEA_all",#标题
color = "red",#GSEA线条颜色
base_size = 20,#基础字体大小
rel_heights = c(1.5, 0.5, 1),#副图的相对高度
subplots = 1:3, #要显示哪些副图 如subplots=c(1,3) #只要第一和第三个图
ES_geom = "line",#enrichment score用线还是用点"dot"
pvalue_table = T) #显示pvalue等信息
gseap2
ggsave(gseap2, filename = "GSEA_up_all.pdf",width =12,height =12)
但如果想使用4.3中的自定义gmt文件,则需要注意,如果生成的gmt文件下使用的是基因SYMBOL,则上面构建排序文件时不需将SYMBOL转换成ENTREZID。
在差异分析结果中取出'SYMBOL'和'log2FoldChange'后,将SYMBOL去重复,再单独取出log2FoldChange的值,使用SYMBOL去对log2FoldChange命名,然后按log2FoldChange排序即可。
need_DEG=need_DEG[duplicated(need_DEG$SYMBOL)==FALSE,]
geneList <- need_DEG$log2FoldChange
names(geneList) <- a$SYMBOL
geneList <- sort(geneList, decreasing = T)
随后就可以使用fgsea进行分析了
#pathway是读入的.gmt文件
fgseaRes <- fgsea(pathway, geneList, minSize=15, maxSize=500, nperm=1000)
fgseaResTidy <- fgseaRes %>% as_tibble() %>% arrange(desc(NES))
fgseaResTidy %>% dplyr::select(-leadingEdge, -ES, -nMoreExtreme) %>% arrange(padj) %>% head()
plotEnrichment(pathway[["gene50"]],geneList) + labs(title="gene50")
✨该教程中的一些小细节:
1. wilcoxauc函数
这个函数来自presto包,可以基于高斯近似法计算Wilcoxon p值和auROC。可以输入Dense matrix/data.frame,Sparse matrix比如dgCMatrix,Seurat V3对象和SingleCellExperiment对象。
2. dplyr:
参考:dplyr包的函数及用法
这里使用到了dplyr包中的4个函数:
filter函数:针对行进行操作,提取一个或多个分组变量中的某个观测
arrange函数:针对某个变量对矩阵进行排序,默认升序
select函数:针对列进行操作,提取指定的一或多列
count函数:对数据集中某个分组变量的各个观测值的数量进行统计
3. fgsea函数:
fgsea能够快速对预选基因集进行GSEA富集分析,预选基因集可以是自己设定,一般使用MSigdb数据库(同样由提出GSEA方法团队提供)。
fgsea()
函数需要一个基因集列表以及对应值,主要是基因名和AUC(ROC曲线下方的面积大小,简单说就是代表准确性,准确性越高,AUC值越大),其中基因集中的基因名要与数据集(pathway)中的基因名相对应。
fgsea包中的plotEnrichment
函数用于GSEA图的绘制。
fgsea函数详细参考:https://stephenturner.github.io/deseq-to-fgsea/
4. msigdbr:
参考:基因功能富集方法和基因注释数据库介绍