DEseq2筛选差异表达基因并注释(bioMart)
DESeq2对于输入数据的要求
1.DEseq2要求输入数据是由整数组成的矩阵。
2.DESeq2要求矩阵是没有标准化的。
DESeq2包分析差异表达基因简单来说只有三步:构建dds矩阵,标准化,以及进行差异分析。
(1)构建dds矩阵
构建dds矩阵需要:
a)表达矩阵:即上述代码中的count,就是通过read count计算后并融合生成的矩阵,行为各个基因,列为各个样品,中间为计算reads或者fragment得到的整数。我们后面要用的是这个文件(readcount.cvs)
b)样品信息矩阵:即上述代码中的colData,它的类型是一个dataframe(数据框),第一列是样品名称,第二列是样品的处理情况(对照还是处理等),即condition,condition的类型是一个factor。这些信息可以从readcount.cvs中导出,也可以自己单独建立。
c)差异比较矩阵:即design。 差异比较矩阵就是告诉差异分析函数是要从要分析哪些变量间的差异,简单说就是说明哪些是对照哪些是处理。
构建dds矩阵的基本代码:
dds <- DESeqDataSetFromMatrix(countData, DataFrame(condition), design= ~ condition )
> library(DESeq2)
> mycounts <- read.csv("/media/yanfang/FYWD/RNA_seq/matrix/readcount.csv")
> head(mycounts)
X control1 control2 treat1 treat2
1 ENSG00000000003 807 357 800 963
2 ENSG00000000005 0 0 0 1
3 ENSG00000000419 389 174 405 509
4 ENSG00000000457 288 108 218 283
5 ENSG00000000460 505 208 451 543
6 ENSG00000000938 0 0 0 0
> rownames(mycounts)<-mycounts[,1] #把第一列当作行名来处理
> mycounts<-mycounts[,-1] #把带X的列删除
> head(mycounts)
control1 control2 treat1 treat2
ENSG00000000003 807 357 800 963
ENSG00000000005 0 0 0 1
ENSG00000000419 389 174 405 509
ENSG00000000457 288 108 218 283
ENSG00000000460 505 208 451 543
ENSG00000000938 0 0 0 0
> condition <- factor(c(rep("control",2),rep("treat",2)), levels = c("control","treat"))
#condition是因子,不是样本名称;对照组和处理组,各两个重复。conditions必须是cloData中的一列
> condition #看一下condition
[1] control control treat treat
Levels: control treat
> colData <- data.frame(row.names=colnames(mycounts), condition)
> colData #看一下colData
condition
control1 control
control2 control
treat1 treat
treat2 treat
> dds <- DESeqDataSetFromMatrix(mycounts, colData, design= ~ condition)
#正式构建dds矩阵
DESeq标准化过程:有这些显示说明是正常运行
DESeq标准化过程> dds_norm <- DESeq(dds) #dds标准化
estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
> dds_norm #查看标准化后的数据
class: DESeqDataSet
dim: 62292 4
metadata(1): version
assays(4): counts mu H cooks
rownames(62292): ENSG00000000003 ENSG00000000005 ... ENSG00000288110 ENSG00000288111
rowData names(22): baseMean baseVar ... deviance maxCooks
colnames(4): control1 control2 treat1 treat2
colData names(2): condition sizeFactor
获取标准化后的数据:
#获取标准化后的数据
> normalized_counts <- counts(dds_norm, normalized=TRUE)
> head(normalized_counts)
control1 control2 treat1 treat2
ENSG00000000003 680.3985 696.3627 670.5922 668.9699158
ENSG00000000005 0.0000 0.0000 0.0000 0.6946728
ENSG00000000419 327.9740 339.4037 339.4873 353.5884602
ENSG00000000457 242.8188 210.6644 182.7364 196.5924052
ENSG00000000460 425.7760 405.7239 378.0464 377.2073357
ENSG00000000938 0.0000 0.0000 0.0000 0.0000000
#根据基因在不同的样本中表达变化的差异程度mad值对数据排序,差异越大的基因排位越前。
> normalized_counts_mad <- apply(normalized_counts, 1, mad)
> normalized_counts <- normalized_counts[order(normalized_counts_mad, decreasing=T), ]
# 标准化后的数据输出
> write.table(normalized_counts, file="dds_normalized_counts.xls",
+ quote=F, sep="\t", row.names=T, col.names=T)
# 只在Linux下能运行,目的是填补表格左上角内容
> system(paste("sed -i '1 s/^/ID\t/'", "dds_normalized_counts.xls"))
# 把输出的标准化后的count取一个log值,log转换后的结果
> rld <- rlog(dds_norm, blind=FALSE)
> rlogMat <- assay(rld)
> rlogMat <- rlogMat[order(normalized_counts_mad, decreasing=T), ]
#把log转化后的数据再输出一个表格
> write.table(rlogMat, file="dds_normalized_counts_rlog.xls",
+ quote=F, sep="\t", row.names=T, col.names=T)
#填补表格左上角内容
> system(paste("sed -i '1 s/^/ID\t/'", "dds_normalized_counts_rlog.xls"))
差异基因分析
> res = results(dds_norm, contrast=c("condition", "control", "treat"))
#使用results()函数获取结果,并赋值给res
# contrast: 定义谁和谁比较
> res = res[order(res$pvalue),]
> head(res)
log2 fold change (MLE): condition control vs treat
Wald test p-value: condition control vs treat
DataFrame with 6 rows and 6 columns
baseMean log2FoldChange lfcSE stat pvalue padj
<numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
ENSG00000178691 531.97208257559 2.89986543009505 0.234227480912105 12.3805516705499 3.33045617928295e-35 2.57277739849608e-31
ENSG00000135535 1195.85832961519 1.23459771315993 0.195266300782888 6.32263584760924 2.57138788753732e-10 9.93198571561288e-07
ENSG00000196504 1798.5833532804 1.12058684067728 0.200292976167903 5.59473857804131 2.20954442255512e-08 5.68957688807944e-05
ENSG00000141425 1314.98437636948 0.969266426507209 0.176627372789244 5.4876342845441 4.07352327905737e-08 7.86699183267955e-05
ENSG00000164172 256.736460977222 1.27926938242781 0.240962413113634 5.3089997145095 1.1022850607365e-07 0.000170303041883789
ENSG00000173905 551.3081531682 1.17836225683544 0.223950630573659 5.26170546524926 1.42725274324417e-07 0.000183758790692687
> summary(res)
# 对res矩阵进行总结,利用summary命令统计显示一共多少个genes上调和下调
out of 31349 with nonzero total read count
adjusted p-value < 0.1
LFC > 0 (up) : 42, 0.13% #42个上调基因
LFC < 0 (down) : 8, 0.026% #8个下调基因
outliers [1] : 0, 0% #没有离群值
low counts [2] : 23624, 75% #75%基因表达量不高,属于low count
(mean count < 166)
[1] see 'cooksCutoff' argument of ?results
[2] see 'independentFiltering' argument of ?results
> write.csv(res,file="All_results.csv") #将所有的数据输出
> table(res$padj<0.05)#取padj小于0.05的数据,得到31行
FALSE TRUE
7694 31
image.png
提取差异基因分析的结果
在利用数据比较分析两个样品中同一个基因是否存在差异表达的时候,一般选取Foldchange值和经过FDR矫正过后的p值,取padj值(p值经过多重校验校正后的值)小于0.05,log2FoldChange大于1的基因作为差异基因集
> diff_gene_deseq2 <-subset(res,padj < 0.05 & (log2FoldChange > 1 | log2FoldChange < -1))
#也可以写成diff_gene_deseq2 <-subset(res, padj < 0.05 & abs(log2FoldChange) > 1)
> dim(diff_gene_deseq2) #访问数组
[1] 15 6
> head(diff_gene_deseq2)
log2 fold change (MLE): condition control vs treat
Wald test p-value: condition control vs treat
DataFrame with 6 rows and 6 columns
baseMean log2FoldChange lfcSE stat pvalue padj
<numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
ENSG00000178691 531.97208257559 2.89986543009505 0.234227480912105 12.3805516705499 3.33045617928295e-35 2.57277739849608e-31
ENSG00000135535 1195.85832961519 1.23459771315993 0.195266300782888 6.32263584760924 2.57138788753732e-10 9.93198571561288e-07
ENSG00000196504 1798.5833532804 1.12058684067728 0.200292976167903 5.59473857804131 2.20954442255512e-08 5.68957688807944e-05
ENSG00000164172 256.736460977222 1.27926938242781 0.240962413113634 5.3089997145095 1.1022850607365e-07 0.000170303041883789
ENSG00000173905 551.3081531682 1.17836225683544 0.223950630573659 5.26170546524926 1.42725274324417e-07 0.000183758790692687
ENSG00000172239 238.384608006302 1.30055924781765 0.252531313724155 5.15009100708309 2.60360094361487e-07 0.000287325961277498
> write.csv(diff_gene_deseq2,file= "DEG_treat_vs_control.csv")
#把所有的差异表达基因输出一个文件
用bioMart对差异表达基因进行注释
bioMart包是一个连接bioMart数据库的R语言接口,能通过这个软件包自由连接到bioMart数据库。这个包可以做以下几个工作:
1.查找某个基因在染色体上的位置。反之,给定染色体每一区间,返回该区间的基因s;
2.通过EntrezGene的ID查找到相关序列的GO注释。反之,给定相关的GO注释,获取相关的EntrezGene的ID;
3.通过EntrezGene的ID查找到相关序列的上游100bp序列(可能包含启动子等调控元件);
4.查找人类染色体上每一段区域中已知的SNPs;
5.给定一组的序列ID,获得其中具体的序列
> library('biomaRt')#载入R包,要用bioMart包从ensembl数据库获得基因的注释
> library("curl")
> mart <- useDataset("hsapiens_gene_ensembl", useMart("ensembl"))
#用useMart函数选定数据库,用useDataset()函数选定数据库中的基因组.
#这条语句的意思是:选定ensembl数据库中的hsapiens_gene_ensembl基因组
> my_ensembl_gene_id<-row.names(diff_gene_deseq2)
> hg_symbols<- getBM(attributes=c('ensembl_gene_id','external_gene_name',"description"),filters = 'ensembl_gene_id', values = my_ensembl_gene_id, mart = mart)
#用getBM()函数获取注释。这个函数有4个参数:
#attributers()里面的值为我们要获取的注释类型,filters()里面的值为我们已知的注释类型
#values= 这个值就是我们已知的注释类型的数据,把上面我们通过数据处理得到的ensembl基因序号作为ensembl_gene_id 的值
#mart= 这个值是我们所选定的数据库的基因组
#mart <- useDataset("hsapiens_gene_ensembl", useMart("ensembl"))
> head(hg_symbols)
ensembl_gene_id external_gene_name description
1 ENSG00000064666 CNN2 calponin 2 [Source:HGNC Symbol;Acc:HGNC:2156]
2 ENSG00000135535 CD164 CD164 molecule [Source:HGNC Symbol;Acc:HGNC:1632]
3 ENSG00000140526 ABHD2 abhydrolase domain containing 2 [Source:HGNC Symbol;Acc:HGNC:18717]
4 ENSG00000144357 UBR3 ubiquitin protein ligase E3 component n-recognin 3 [Source:HGNC Symbol;Acc:HGNC:30467]
5 ENSG00000152818 UTRN utrophin [Source:HGNC Symbol;Acc:HGNC:12635]
6 ENSG00000163848 ZNF148 zinc finger protein 148 [Source:HGNC Symbol;Acc:HGNC:12933]
> ensembl_gene_id<-rownames(diff_gene_deseq2)
> diff_gene_deseq2<-cbind(ensembl_gene_id,diff_gene_deseq2)
> colnames(diff_gene_deseq2)[1]<-c("ensembl_gene_id")
> diff_name<-merge(diff_gene_deseq2,hg_symbols,by="ensembl_gene_id")
#把注释文件和基因表达量文件合并起来
> head(diff_name)
DataFrame with 6 rows and 9 columns
ensembl_gene_id baseMean log2FoldChange lfcSE stat pvalue padj
<character> <numeric> <numeric> <numeric> <numeric> <numeric> <numeric>
1 ENSG00000064666 233.649167762814 -1.05516841956132 0.261201368199475 -4.03967416723294 5.3525508533232e-05 0.0179775892790964
2 ENSG00000135535 1195.85832961519 1.23459771315993 0.195266300782888 6.32263584760924 2.57138788753732e-10 9.93198571561288e-07
3 ENSG00000140526 454.248659298761 1.09955045620162 0.244298072590034 4.50085604255593 6.76803336861755e-06 0.00326769111078566
4 ENSG00000144357 411.010386096953 1.00761195016462 0.244841355759736 4.11536665053185 3.86564433730833e-05 0.0149310512528534
5 ENSG00000152818 568.00627589957 1.22331171400082 0.254288749757859 4.81071897661886 1.50388340150822e-06 0.0011617499276651
6 ENSG00000163848 315.923451036876 1.12786190454491 0.232224503174498 4.85677389391337 1.19313704152794e-06 0.00102410929397815
external_gene_name description
<character> <character>
1 CNN2 calponin 2 [Source:HGNC Symbol;Acc:HGNC:2156]
2 CD164 CD164 molecule [Source:HGNC Symbol;Acc:HGNC:1632]
3 ABHD2 abhydrolase domain containing 2 [Source:HGNC Symbol;Acc:HGNC:18717]
4 UBR3 ubiquitin protein ligase E3 component n-recognin 3 [Source:HGNC Symbol;Acc:HGNC:30467]
5 UTRN utrophin [Source:HGNC Symbol;Acc:HGNC:12635]
6 ZNF148 zinc finger protein 148 [Source:HGNC Symbol;Acc:HGNC:12933]
查看CD164的情况:
> CD164 <- diff_name[diff_name$external_gene_name=="CD164",]
> CD164
DataFrame with 1 row and 9 columns
ensembl_gene_id baseMean log2FoldChange lfcSE stat pvalue padj external_gene_name
<character> <numeric> <numeric> <numeric> <numeric> <numeric> <numeric> <character>
1 ENSG00000135535 1195.85832961519 1.23459771315993 0.195266300782888 6.32263584760924 2.57138788753732e-10 9.93198571561288e-07 CD164
description
<character>
1 CD164 molecule [Source:HGNC Symbol;Acc:HGNC:1632]
数据可视化
1.MA plot
MA-plot ,也叫 mean-difference plot或者Bland-Altman plot,用来估计模型中系数的分布。 X轴, the “A” ( “average”);Y轴,the “M” (“minus”) – subtraction of log values is equivalent to the log of the ratio。M表示log fold change,衡量基因表达量变化,上调还是下调。A表示每个基因的count的均值。根据summary可知,low count的比率很高,所以大部分基因表达量不高,也就是集中在0的附近(log2(1)=0,也就是变化1倍).提供了模型预测系数的分布总览。
library(ggplot2)
library(BiocGenerics)
plotMA(res,ylim=c(-2,2))
topGene <- rownames(res)[which.min(res$padj)]
with(res[topGene, ], {
points(baseMean, log2FoldChange, col="dodgerblue", cex=6, lwd=2)
text(baseMean, log2FoldChange, topGene, pos=2, col="dodgerblue")
})
image.png
lfcShrink 收缩log2 fold change
> res_order<-res[order(row.names(res)),]
#前面res结果已经按padj排序了,所以这次要按照行名升序再排列回来,否则和dds不一致
> res = res_order
> res.shrink <- lfcShrink(dds, contrast = c("condition","treat","control"), res=res)
#将DESeq函数处理后生成的的dds对象传递给lfcShrink函数即可
> plotMA(res.shrink, main="DESeq2", ylim = c(-5,5))
> topGene <- rownames(res)[which.min(res$padj)]
> with(res[topGene, ], {
+ points(baseMean, log2FoldChange, col="dodgerblue", cex=2, lwd=2)
+ text(baseMean, log2FoldChange, topGene, pos=2, col="dodgerblue")
+ })
效果好的话,收缩的图形不会出现左宽右窄。
image.png火山图 原始数据来源:https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE50177
>BiocManager::install("EnhancedVolcano")
>library(EnhancedVolcano)
>library(airway)
>EnhancedVolcano(res,
lab = rownames(res),
x = 'log2FoldChange',
y = 'pvalue',
xlim = c(-8, 8),
title = 'resistant versus control',
pCutoff = 10e-17,
FCcutoff = 2,
transcriptPointSize = 1.5,
transcriptLabSize = 3.0,
col=c('black', 'blue', 'green', 'red1'),
colAlpha = 1,
legend=c('NS','Log2 fold-change','P value',
'P value & Log2 fold-change'),
legendPosition = 'right',
legendLabSize = 14,
legendIconSize = 5.0,
)
image.png
箱图
> plotCounts(dds, gene="ENSG00000064666", intgroup="condition", returnData=TRUE) %>%
+ ggplot(aes(condition, count)) + geom_boxplot(aes(fill=condition)) + scale_y_log10() + ggtitle("CNN2")
image.png
PCA(principal components analysis)
热图(heatmap), PCA或聚类(clustering)我们需要data的转换后的格式。
在DESeq2包中专门由一个PCA分析的函数,即plotPCA。在DESeq2包中实际上已经有了归一化的方法,rlog和vst。在使用的需要根据样本量的多少来选择方法。样本量少于30的话,选择rlog,多于30的话,建议选择vst。
#归一化,因为样本量超过了30,因此用vst
> vsdata <- vst(dds, blind=FALSE)
> plotPCA(vsdata, intgroup="condition")
#intgroup:也就是在构建dds的时候的分组,实际上这个分组最后影响的是PCA图中的颜色,但是并不影响PCA图中各个样本的位置。
#这个参数的作用就是当你的PCA图需要加样本名的时候,也就是你希望在PCA图上知道哪个点是哪个样本,你就需要导出这个。
image.png
热图
1.count matrix 热图
library("pheatmap")
有两种方式,画出来的图是一样的。
第一种:
> select<-order(rowMeans(counts(dds_norm, normalized = TRUE)),decreasing = TRUE)[1:20]
> df <- as.data.frame(colData(dds_norm)[,c("condition","sizeFactor")])
> pheatmap(assay(ntd)[select,], cluster_rows=FALSE, show_rownames=FALSE,cluster_cols=FALSE, annotation_col=df)
第二种:
> ntd <- normTransform(dds_norm)
> pheatmap(assay(ntd)[select,], cluster_rows=FALSE, show_rownames=FALSE,
+ cluster_cols=FALSE, annotation_col=df)
画出来的图都是这样:
image.pngsample-to-sample distances热图
转换数据还可以做出样本聚类热图。用dist函数来获得sample-to-sample距离。距离矩阵热图中可以清楚看到samples之间的相似与否的总概。需要给heatmap函数基于sample距离提供等级聚类hc。
首先调用RColorBrewer包,这个包的说明请见:https://www.jianshu.com/p/a8856757a0d2
> library("RColorBrewer")
> sampleDists <- dist(t(assay(vsdata)))
> sampleDistMatrix <- as.matrix(sampleDists)
> rownames(sampleDistMatrix) <- paste(vsdata$condition, vsdata$type, sep="-")
> colnames(sampleDistMatrix) <- NULL
> colors <- colorRampPalette( rev(brewer.pal(9, "Oranges")) )(255)
> pheatmap(sampleDistMatrix,
+ clustering_distance_rows=sampleDists,
+ clustering_distance_cols=sampleDists,
+ col=colors)
image.png
功能富集分析
A:差异基因富集分析(不需要表达值,只需要gene name)
最常用的基因注释工具是GO和KEGG注释,这基本上是差异基因分析一定做的两件事。GO可以在GO:BP(生物过程),GO:MF(分子功能),GO:CC(细胞组分)三个方面分别进行注释,用的比较多的是GO:BP,但其他两方面也很重要。得到的差异表达基因列表就可以,也就是说不需要其他的值(https://www.jianshu.com/p/5d82acad6008)
拿什么来富集? 得到的差异表达基因列表就可以。
B: 基因集(gene set)富集分析(不管有无差异,需要全部genes表达值)
好处:可以发现被差异基因舍弃的genes可能参与了某重要生理过程或信号通路。工具:GSEA
library(clusterProfiler)
library(DOSE)
library(org.Hs.eg.db)
setwd("/media/yanfang/FYWD/RNA_seq/matrix/")
sig.gene<-read.csv(file="readcount_all.csv")#用DEG_treat_vs_control.csv后续分析没有富集到,所以换用这个
head(sig.gene)
gene<-sig.gene[,2] #ID所在的列
head(gene)
gene.df<-bitr(gene, fromType = "ENSEMBL",
toType = c("SYMBOL","ENTREZID"),
OrgDb = org.Hs.eg.db)
# 人类样品用org.Hs.eg.db;小鼠用org.Mm.eg.db
head(gene.df)
library("stringr")
GO_CC富集
ego_cc <- enrichGO(gene = gene.df$ENSEMBL,
OrgDb = org.Hs.eg.db,
keyType = 'ENSEMBL',
ont = "CC",
pAdjustMethod = "BH",
pvalueCutoff = 0.01,
qvalueCutoff = 0.05)
barplot(ego_cc,showCategory = 18,title="The GO_CC enrichment analysis of all DEGs ")+
scale_size(range=c(2, 12))+
scale_x_discrete(labels=function(ego_cc) str_wrap(ego_cc,width = 25))
GO_BP富集
ego_bp <- enrichGO(gene = gene.df$ENSEMBL,
OrgDb = org.Hs.eg.db,
keyType = 'ENSEMBL',
ont = "BP",
pAdjustMethod = "BH",
pvalueCutoff = 0.01,
qvalueCutoff = 0.05)
barplot(ego_bp,showCategory = 18,title="The GO_BP enrichment analysis of all DEGs ")+
scale_size(range=c(2, 12))+
scale_x_discrete(labels=function(ego_bp) str_wrap(ego_bp,width = 25))
image.png
image.png
#功能富集分析气泡图
#这个结果是另一篇文献中的数据得来的
dotplot(ego_bp, font.size=10)
image.png
#GO图
plotGOgraph(ego_bp)
image.png
KEGG富集分析
KEGG将基因组信息和高一级的功能信息有机地结合起来,通过对细胞内已知生物学过程的计算机化处理和将现有的基因功能解释标准化,对基因的功能进行系统化的分析。
KEGG的另一个任务是一个将基因组中的一系列基因用一个细胞内的分子相互作用的网络连接起来的过程,如一个通路或是一个复合物,通过它们来展现更高一级的生物学功能。
参考文章:http://blog.sciencenet.cn/blog-364884-779116.html
KEGG物种缩写:http://www.genome.jp/kegg/catalog/org_list.html
GO和KEGG输出文件解读:http://www.bio-info-trainee.com/370.html
#这里我用另外的一篇文献里的原始数据做的图
>library(stringr)
>kk<-enrichKEGG(gene =gene.df$ENTREZID,
organism = 'hsa',
pvalueCutoff = 0.05)
>kk[1:30]
>barplot(kk,showCategory = 25, title="The KEGG enrichment analysis of all DEGs")+
scale_size(range=c(2, 12))+
scale_x_discrete(labels=function(kk) str_wrap(kk,width = 25))
>dotplot(kk,showCategory = 25, title="The KEGG enrichment analysis of all DEGs")+
scale_size(range=c(2, 12))+
scale_x_discrete(labels=function(kk) str_wrap(kk,width = 25))
image.png
Gene Set Enrichment Analysis(GSEA)
基因集富集分析 (Gene Set Enrichment Analysis, GSEA) 的基本思想是使用预定义的基因集(通常来自功能注释或先前实验的结果),将基因按照在两类样本中的差异表达程度排序,然后检验预先设定的基因集合是否在这个排序表的顶端或者底端富集。基因集合富集分析检测基因集合而不是单个基因的表达变化,因此可以包含这些细微的表达变化,预期得到更为理想的结果。(https://www.jianshu.com/p/4910d7cec5c8)
参考资料:GSEA分析是什么鬼(上)和GSEA分析是什么鬼(下)。
setwd("/media/yanfang/FYWD/RNA_seq/matrix/")
sig.gene <- read.csv(file="DEG_resistant_vs_control.csv")
genelist <- sig.gene$log2FoldChange
names(genelist) <- sig.gene[,1]
genelist <- sort(genelist, decreasing = TRUE)
gsemf <- gseGO(genelist, OrgDb = org.Hs.eg.db, keyType = "ENSEMBL", ont="BP")#OrgDb:指定物种注释数据。keytype:ID类型
head(gsemf)
gseaplot(gsemf, geneSetID="GO:0030198")
image.png
网友评论