前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >先差异后GSEA呢还是先ssGSEA后差异呢

先差异后GSEA呢还是先ssGSEA后差异呢

作者头像
生信技能树
发布2022-07-26 10:44:44
1.3K0
发布2022-07-26 10:44:44
举报

转录组等表达量数据处理大家都是蛮熟悉的了,无论是传统的芯片还是转录组测序,最后都是得到一些样品在几万个基因的表达量矩阵。一般来说,样品需要有分组,这样才有差异分析的可能,最简单的就是处理和对照的二分组。

如果我们想搞清楚处理前后到底两个分组有什么差异,其实可选的数据分析路线还蛮多的:

  • 方案1:分组做一个差异分析,根据阈值确定统计学显著的几百个上下调基因,然后分别注释其功能
  • 方案2:分组做一个差异分析,根据变化情况把几万个基因排序后,进行gsea分析来确定上下调通路功能
  • 方案3:针对每个样品的基因表达量排序进行ssGSEA分析,然后对ssGSEA打分矩阵根据分组进行差异分析

我们一直以来都是给大家前面的两个方案,就是一定要先根据表达量矩阵做不同分组的差异,而且两者的结果一致性都还不错。但是前面的两个方案都会手动一个批次效应的影响,如果大家没有把握好其中的批次效应的去除,很容易在差异分析阶段就不小心引入了错误。

实际上,最后的方案,就是针对每个样品的基因表达量排序进行ssGSEA分析,然后对ssGSEA打分矩阵根据分组进行差异分析理论上可以跨越批次效应的,而且如果它的结果跟前面的两个方案差异也不大,我们后续遇到了无法去除的批次效应情况就可以走它了。

这里仍然是以airway数据集为例子

airway数据集可以说是最出名的转录组测序数据了,因为各大教程和授课资料都是以它为案例来讲解转录组差异分析,它就在 airway的包里面,如下所示的代码:


# 1.构建表达矩阵 ----------------------------------------------------------------
dir.create("./data")

# 魔幻操作,一键清空
rm(list = ls()) 
options(stringsAsFactors = F)
# BiocManager::install('airway')
# 加载airway数据集并转换为表达矩阵
library(airway,quietly = T)
data(airway)
class(airway)

rawcount <- assay(airway)
colnames(rawcount)

# 查看表达谱
rawcount[1:4,1:4]

# 去除前的基因表达矩阵情况
dim(rawcount)

# 获取分组信息
group_list <- colData(airway)$dex
group_list

# 过滤在至少在75%的样本中都有表达的基因
keep <- rowSums(rawcount>0) >= floor(0.75*ncol(rawcount))
table(keep)

filter_count <- rawcount[keep,]
filter_count[1:4,1:4]
dim(filter_count)

# 加载edgeR包计算counts per millio(cpm) 表达矩阵,并对结果取log2值
library(edgeR)
express_cpm <- log2(cpm(filter_count)+1)
express_cpm[1:6,1:6]

# 保存表达矩阵和分组结果
save(filter_count,
     express_cpm,
     group_list,
     file = "./data/Step01-airwayData.Rdata") 

大家可以先自行理解这个airway数据集,它的转录组测序数据也是公开可以获取的, 可以看我们的数据分析实战系列教程,目录如下所示:

前面我们提到了可选的数据分析路线有3个:

  • 方案1:分组做一个差异分析,根据阈值确定统计学显著的几百个上下调基因,然后分别注释其功能
  • 方案2:分组做一个差异分析,根据表达量变化情况把几万个基因排序后,进行gsea分析来确定上下调通路功能
  • 方案3:针对每个样品的基因表达量排序进行ssGSEA分析,然后对ssGSEA打分矩阵根据分组进行差异分析

前面的两个方案都需要做差异分析,接下来我们就走转录组差异分析

先差异后GSEA

转录组差异分析,我们针对测序的counts矩阵,走DESeq2这个r包的方法:

 
exprSet <- filter_count
dim(exprSet)
exprSet[1:6,1:6]
table(group_list)

# 加载包
library(DESeq2)

# 第一步,构建DESeq2的DESeq对象
colData <- data.frame(row.names=colnames(exprSet),group_list=group_list)
dds <- DESeqDataSetFromMatrix(countData = exprSet,colData = colData,design = ~ group_list)

# 第二步,进行差异表达分析
dds2 <- DESeq(dds)

# 提取差异分析结果,trt组对untrt组的差异分析结果
tmp <- results(dds2,contrast=c("group_list","trt","untrt"))
DEG_DESeq2 <- as.data.frame(tmp[order(tmp$padj),])
head(DEG_DESeq2)

# 去除差异分析结果中包含NA值的行
DEG_DESeq2 = na.omit(DEG_DESeq2) 
head(DEG_DESeq2)
library(AnnoProbe)
ag=annoGene(rownames(DEG_DESeq2),
         ID_type = 'ENSEMBL',species = 'human'
            )
head(ag)
DEG_DESeq2$ENSEMBL=rownames(DEG_DESeq2)
 
deg_anno=merge(ag,DEG_DESeq2,by='ENSEMBL')
head(deg_anno)
# 保存 
save(deg_anno, file = "./data/Step03-DESeq2_nrDEG.Rdata")

有了差异分析结果,我们先走方案2:分组做一个差异分析,根据变化情况把几万个基因排序后,进行gsea分析来确定上下调通路功能:

rm(list = ls())
options(stringsAsFactors = F)
load(file = "./data/Step03-DESeq2_nrDEG.Rdata") 

library(clusterProfiler)
library(org.Hs.eg.db)
# 转成ENTREZID
df <- bitr(unique(deg_anno$SYMBOL), fromType = "SYMBOL",
           toType = c( "ENTREZID"),
           OrgDb = org.Hs.eg.db) 
DEG=merge(deg_anno,df,by='SYMBOL')
colnames(DEG)
data_all_sort <- DEG %>%  #排序
  arrange(desc(log2FoldChange))
geneList = data_all_sort$log2FoldChange #把foldchange按照从大到小提取出来
names(geneList) <- data_all_sort$ENTREZID #给上面提取的foldchange加上对应上ENTREZID
head(geneList) #排序好的基因序列,而且是entrezeID的形式

R.utils::setOption( "clusterProfiler.download.method",'auto' )
kkgsea <- gseKEGG(geneList     = geneList,
               organism     = 'hsa', 
               minGSSize    = 3,
               maxGSSize    = 5000,
               pvalueCutoff = 1,
               pAdjustMethod = "none" ) #进行gseKEGG富集分析 
tmp = kkgsea@result
save(kkgsea,file = 'gsea_kk.Rdata') 

一般来说,这个 clusterProfiler 包里面的gseKEGG会在线获取kegg数据库的三百多通路,并且全部进行fix。

先ssGSEA后差异

这里我们针对测序的counts矩阵,走GSVA包的ssGSEA分析,代码如下所示:

rm(list = ls())
options(stringsAsFactors = F) 
load(file = "./data/Step01-airwayData.Rdata")
express_cpm[1:6,1:6]
table(group_list)

library(msigdbr)  #install.packages("msigdbr")
library(GSVA) 
library(GSEABase)
library(pheatmap)
library(limma) 

## msigdbr包提取下载  KEGG数据集
KEGG_df_all <-  msigdbr(species = "Homo sapiens", # Homo sapiens or Mus musculus
                        category = "C2",
                        subcategory = "CP:KEGG") 
colnames(KEGG_df_all)
KEGG_df <- dplyr::select(KEGG_df_all,gs_exact_source,gs_exact_source,ensembl_gene)  
kegg_list <- split(KEGG_df$ensembl_gene, KEGG_df$gs_exact_source)  
kegg_list
 
names(kegg_list)
ssgsea_mat <- gsva(expr=express_cpm, 
                 method='ssgsea',
                 gset.idx.list=kegg_list,  
                 verbose=T, 
                 parallel.sz = 4 )#调用所有核,行名变成通路名
ssgsea_mat[1:4,1:4]
library(limma)
g=factor( group_list ,levels = c('untrt','trt'))
design=model.matrix(~g)
fit=lmFit(ssgsea_mat,design)
fit=eBayes(fit)
## 上面是limma包用法的一种方式 
options(digits = 4) #设置全局的数字有效位数为4
#topTable(fit,coef=2,adjust='BH') 
ssgsea_deg = topTable(fit,coef=2,adjust='BH', n=Inf) 
save(ssgsea_deg,file = 'ssgsea_deg.Rdata') 

因为是msigdbr包提取下载KEGG数据集,所以通路就不到两百个哦。

对比一下

因为两次分析选取的kegg数据源头不一样,所以需要根据ID进行简单的交集:

rm(list = ls())
options(stringsAsFactors = F) 
load(file = 'ssgsea_deg.Rdata')
load(file = 'gsea_kk.Rdata')

deg_gsea = kkgsea@result
gsea_deg = ssgsea_deg

ids = intersect(rownames(deg_gsea),
                rownames(ssgsea_deg)) #186条中有184条,换了个富集源,从40显著增加

# 02构建可视化所需的矩阵(相关性就两行值)
df=data.frame(
  ssgsea_deg=ssgsea_deg[ ids,"logFC"],
  deg_gsea=deg_gsea[ ids,"enrichmentScore"] #就是两列logFC的值(散点图)
)
deg_gsea=deg_gsea[ ids,]
df$Description=deg_gsea$Description  #加名字了的,可视化了的

library(ggstatsplot)
#BiocManager::install("ggpmisc")
library(ggpmisc)
p <- ggplot(df, aes(x=ssgsea_deg,
                    deg_gsea)) +    
  geom_point() +
  labs(x = "ssgsea_deg",
       y = "deg_gsea")+
  scale_color_manual(values=c("blue", "grey","red"))+
  #geom_vline(xintercept = c( -1.5,0,1.5),lty=4,col="#ec183b",lwd=0.8) +
  # geom_hline(yintercept =  c( -1.5,0,1.5),lty=4,col="#18a5ec",lwd=0.8) +
  #xlim(-5,5)+
  ylim(-1,1)+
  theme_ggstatsplot()+
  theme(panel.grid.minor = element_blank(),
        panel.grid.major = element_blank())
p
p+stat_poly_eq(aes(label=paste(..eq.label..,..adj.rr.label..,..p.value.label..,sep = "~~~~")),formula = y~x,parse=T,size=3.0)

可以看到, 两个策略得到的结果其实是大同小异:

两个策略得到的结果其实是大同小异

同理,大家也可以测试一下方案1和2的一致性,差异分析后的统计学显著的上下调基因分别独立去做GO或者KEGG数据库的超几何分布检验结果,跟上面提到的先差异后GSEA结果是否有很大区别。

再次强调一下可选的数据分析路线有3个:

  • 方案1:分组做一个差异分析,根据阈值确定统计学显著的几百个上下调基因,然后分别注释其功能
  • 方案2:分组做一个差异分析,根据表达量变化情况把几万个基因排序后,进行gsea分析来确定上下调通路功能
  • 方案3:针对每个样品的基因表达量排序进行ssGSEA分析,然后对ssGSEA打分矩阵根据分组进行差异分析

你喜欢哪一个呢?

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 生信技能树 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 这里仍然是以airway数据集为例子
  • 先差异后GSEA
  • 先ssGSEA后差异
  • 对比一下
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档