下面对“GSE78179”进行GEO实战分析
第一部分 读入
1、读入数据
options(stringsAsFactors = F) #命令:不要把字符串自动转化成因子
library(GEOquery)
eSet <- getGEO("GSE78179",
destdir = '.', #destdir下载到哪里,'.'当前目录
getGPL = F)
解释:
destdir
下载到哪里,'.'当前目录
Q:得到的eSet是一个大list,怎样从中提取表达矩阵? A:用 exprs()
读取
2、将eSet内的六组芯片表达读出来(此时的eSet为list)
class(eSet)
length(eSet)
class(eSet[[1]])
exp <- exprs(eSet[[1]])
pd <- pData(eSet[[1]])
save(pd,exp,file = "step1output.Rdata")
注意:
①当读入进eSet之后,我们需要查看平台(GPL)eSet[[1]]@annotation
,因为后期芯片和包为一一对应,方便ID转换
②eSet
中含有很多的信息,如exprs、pdata、assayData等,eSet
是包含很多相关数据的一个集合包
③pData
为查看临床信息
④
第二部分 设置分组信息
①查看dat的格式,非常规整。连续三个为肿瘤,连续三个为健康,所以我们可以用
group_list=c(rep("Control",times=3),rep("treat",times=3))
自己加上分组信息
②这一步是对输入的数据进行修整,为后续作PCA,heaatmap,volcano等图做准备。
class(pd)
dim(pd)
colnames(pd)
group_list=c(rep("Control",times=3),rep("treat",times=3))
group_list
save(group_list,file = "step2output.Rdata")
class(pd)
exp[1:4,1:4] #之前exp为矩阵
dat=as.data.frame(t(exp)) #这一步是将行与列发生了转换
dim(exp)
dim(dat)
dat=cbind(dat,group_list)
第三部分 PCA作图
library(FactoMineR)
library(factoextra)
dat.pca <- PCA(dat[,-ncol(dat)], graph = FALSE)
fviz_pca_ind(dat.pca,
geom.ind = "point",
col.ind = dat$group_list,
palette = c("#00AFBB", "#E7B800"),
addEllipses = TRUE,
legend.title = "Groups")
出个PCA图see
如果你不理解,咱们再看一个:
说明:
①以上两个PCA图是一样的,需要我们理解的是:
我们做PCA数据的输入文件是
dat.pca
,而dat.pca
是在dat
的基础上添加了一列分组信息,所以得到的PCA图中每一个pouint代表一个sample 正如你在图二看到的这样。
②关于PCA的输入数据,注意A-C:
A、PCA作图的输入数据为PCA格式,这一步得到的是
dat.pca
,是一个list
B、如果要得到
dat.pca
,可以查看PCA
函数。参照函数dat.pca <- PCA(dat[,-ncol(dat)], graph = FALSE)
C、
PCA
的输入数据为数值型,而经过上一步的数据处理,dat的数据类型为data.frame,并且最后一列为字符串型,所以要将dat的最后一列删除变为数值型。
———————————————————————————————————————
总结制图PCA流程
利用GEO得到eSet[一个大list]
↓
expre提取表达矩阵exp
↓
exp为matrix,转为data.frame(为后续的PCA输入文件)
↓
加分组信息(group_list
),在制图PCA命令中添加分组信息,制备差异分组可视化
↓
制作PCA的标准数据形式
↓
制PCA~
———————————————————————————————————————
第四部分 热图
1、做基因方差并挑选差异大的基因(tail()
)
cg=names(tail(sort(apply(exp,1,sd)),1000))
library(pheatmap)
pheatmap(exp[cg,],
show_colnames = F,
show_rownames = F)
Resullt:
该结果显示的热图,差异并不明显。所以需要做归一化处理。
2、理解归一化:
①数据归一化包括数据的中心化和数据的标准化
②归一化化就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保证程序运行时收敛加快;一般选择的数据的范围落在[0,1]之间
②‘A、数据的中心化
所谓数据的中心化是指数据集中的各项数据减去数据集的均值。
例如有数据集1, 2, 3, 6, 3,其均值为3,那么中心化之后的数据集为1-3,2-3,3-3,6-3,3-3,即:-2,-1,0,3,0
B、数据的标准化
所谓数据的标准化是指中心化之后的数据在除以数据集的标准差,即数据集中的各项数据减去数据集的均值再除以数据集的标准差。
例如有数据集1, 2, 3, 6, 3,其均值为3,其标准差为1.87,那么标准化之后的数据集为(1-3)/1.87,(2-3)/1.87,(3-3)/1.87,(6-3)/1.87,(3-3)/1.87,即:-1.069,-0.535,0,1.604,0
③数据中心化和标准化的意义是一样的,为了消除量纲对数据结构的影响。在R语言中可以使用scale方法来对数据进行中心化和标准化。
经验之谈:如果在做运行的过程中,发现前后的代码都一样,只是因为未命名而导致结果出现偏差,请将未命名的一组赋值即可
cg=names(tail(sort(apply(exp,1,sd)),1000))
library(pheatmap)
pheatmap(exp[cg,],
show_colnames = F,
show_rownames = F)
n=t(scale(t(exp[cg,]))) #t代表转置,并且转置后的数据类型为matrix
thr=1.5
n[n>thr]=thr
n[n< -thr]= -thr
n[1:4,1:4]
pheatmap(n,show_colnames =F,show_rownames = F)
说明:
thr代表Through hole reflow,这里表示为表达量的范围在1与-1之间 正如thr=1
3、出图(heatmap)
Result:
[注意细节]如果改变thr的值,如
thr=2
,则result为:
4、加注释分组(
annotation_col
)
ac=data.frame(group=group_list)
rownames(ac)=colnames(n)
pheatmap(n,show_colnames =F,show_rownames = F,
annotation_col=ac)
[注意]注释分组ac
的内容包括样本号以及group信息
——————————————————————————————————————
绘制热图总结:
对基因求sd
↓
挑选差异大的基因(选择tail()
)
↓
绘制热图(绘制热图的输入数据为matrix
)
——————————————————————————————————————
第五部分 箱图
给箱图加分组注释信息
table(group_list)
boxplot(exp[1,]~group_list)
Result:
第六部分 火山图
library(ggpubr)
df=data.frame(gene=g,group=group_list)
p <- ggboxplot(df, x = "group", y = "gene",
color = "group", palette = "jco",
add = "jitter")
# Add p-value
p + stat_compare_means(label.y = 8)
}
bp(exp[1,])
Result:
library(limma)
design=model.matrix(~factor(group_list))
fit=lmFit(exp,design)
fit=eBayes(fit)
deg=topTable(fit,coef=2,number = Inf)
head(deg)
deg$logFC <- -(deg$logFC)
bp(exp[rownames(deg)[1],]) ##
bp(exp[rownames(deg)[2],])
library(dplyr)
deg <- mutate(deg,probe_id=rownames(deg))
此处要将deg添加一列probe_id,以备后续做基因转换ID
library(HsAgilentDesign026652.db)
#library(hugene10sttranscriptcluster.db)
ls("package:HsAgilentDesign026652.db")
ids <- toTable(HsAgilentDesign026652SYMBOL)
head(ids)
注意:
①不同的GPL,会选择不同的包。
②查询GPL有两种方法:A、eSet[[1]]@annotation
B、eSet[[1]]
③id转换,查找芯片平台对应的包的网址为:http://www.bio-info-trainee.com/1399.html
ids:
deg:
根据id与deg的共同一列probe_id 将两者合并。
deg <- inner_join(deg,ids,by="probe_id")
head(deg)
开始绘制火山图的输入数据文件。在上一步的操作中,已经成功匹配出probe_id以及symbol,接下来要根据logFC、p.value对基因匹配up或down。最后,将deg与匹配出的stable、up、down进行合并,进行基因ID转换,因为火山图要以logFC
为横坐标,p.value
为纵坐标。所以输入文件中必然存在相关信息,输入数据文件完毕。
logFC_t=2
change=ifelse(deg$P.Value>0.01,'stable',
ifelse( deg$logFC >logFC_t,'up',
ifelse( deg$logFC < -logFC_t,'down','stable') )
)
deg <- mutate(deg,change)
head(deg)
table(deg$change)
library(ggplot2)
library(clusterProfiler)
library(org.Hs.eg.db)
s2e <- bitr(unique(deg$symbol), fromType = "SYMBOL", #unique(deg$symbol)去重复
toType = c( "ENTREZID"),
OrgDb = org.Hs.eg.db) #ID转换函数:bitr ,这个步骤会损失一些基因。
head(s2e)
head(deg)
deg <- inner_join(deg,s2e,by=c("symbol"="SYMBOL"))
head(deg)
save(group_list,deg,file = "step4output.Rdata")
绘制火山图
plot(deg$logFC,-log10(deg$P.Value))
Result:
如你所见,这个火山图很丑。
接下来,对火山图进行修饰与整理:
library(dplyr)
dat <- mutate(deg,v=-log10(P.Value))
head(dat)
library(ggplot2)
ggplot(dat,aes(logFC,v))+
geom_point() #aes映射
library(ggpubr)
ggscatter(dat, x = "logFC", y = "v")
ggscatter(dat, x = "logFC", y = "v",size = 0.5)
table(dat$change)
ggscatter(dat, x = "logFC", y = "v",size=0.5,color = "change",palette = c("#FF6347", "#0A0A0A", "#87CEFA"))
Result:
—————————————————————————————————————
绘制火山图总结:
①制作出符合绘制火山图的输入文件(包含logFC、p.value、基因ID)
↓
②选值方面:设定logFC,P值的大小,从而选择合适的stable、up、down基因
↓
③关于火山图的相关修饰查看帮助文档即可
↓
④绘制火山图
—————————————————————————————————————
关于理解火山图推荐web:
http://www.360doc.com/content/17/0730/23/45852776_675457183.shtml
第七部分 GO、KEGG分析
if(T){
library(clusterProfiler)
gene_up= deg[deg$change == 'up','ENTREZID']
gene_down=deg[deg$change == 'down','ENTREZID']
gene_diff=c(gene_up,gene_down)
gene_all = deg[,'ENTREZID']
kk.up <- enrichKEGG(gene = gene_up,
organism = 'hsa',
universe = gene_all,
pvalueCutoff = 0.9,
qvalueCutoff =0.9) #核心为 enrichKEGG()
head(kk.up)[,1:6]
dim(kk.up)
kk.down <- enrichKEGG(gene = gene_down,
organism = 'hsa',
universe = gene_all,
pvalueCutoff = 0.9,
qvalueCutoff =0.9) #qvalueCutoff=1/0.9:所有的富集结果都拿出来
head(kk.down)[,1:6]
dim(kk.down)
kk.diff <- enrichKEGG(gene = gene_diff,
organism = 'hsa',
pvalueCutoff = 0.05)
head(kk.diff)[,1:6]
class(kk.diff)
#提取出数据框
kegg_diff_dt <- kk.diff@result
#根据pvalue来选,用于可视化
down_kegg <- kk.down@result %>%
filter(pvalue<0.01) %>%
mutate(group=-1)
up_kegg <- kk.up@result %>%
filter(pvalue<0.01) %>%
mutate(group=1)
#可视化走起
kegg_plot <- function(up_kegg,down_kegg){
dat=rbind(up_kegg,down_kegg)
colnames(dat)
dat$pvalue = -log10(dat$pvalue)
dat$pvalue=dat$pvalue*dat$group
dat=dat[order(dat$pvalue,decreasing = F),]
g_kegg<- ggplot(dat, aes(x=reorder(Description,order(pvalue, decreasing = F)), y=pvalue, fill=group)) +
geom_bar(stat="identity") +
scale_fill_gradient(low="blue",high="red",guide = FALSE) +
scale_x_discrete(name ="Pathway names") +
scale_y_continuous(name ="-log10Pvalue") +
coord_flip() +
theme_bw()+
theme(plot.title = element_text(hjust = 0.5))+
ggtitle("Pathway Enrichment")
}
g_kegg <- kegg_plot(up_kegg,down_kegg)
g_kegg
ggsave(g_kegg,filename = 'kegg_up_down.png')
}
#gsea作kegg富集分析
if(F){
data(geneList, package="DOSE")
head(geneList)
length(geneList)
names(geneList)
boxplot(geneList)
boxplot(deg$logFC)
geneList=deg$logFC
names(geneList)=deg$ENTREZID
geneList=sort(geneList,decreasing = T)
kk_gse <- gseKEGG(geneList = geneList,
organism = 'hsa',
nPerm = 1000,
minGSSize = 120,
pvalueCutoff = 0.9,
verbose = FALSE)
head(kk_gse)[,1:6]
gseaplot(kk_gse, geneSetID = rownames(kk_gse[1,]))
down_kegg<-kk_gse[kk_gse$pvalue<0.05 & kk_gse$enrichmentScore < 0,];down_kegg$group=-1
up_kegg<-kk_gse[kk_gse$pvalue<0.05 & kk_gse$enrichmentScore > 0,];up_kegg$group=1
g_kegg=kegg_plot(up_kegg,down_kegg)
print(g_kegg)
ggsave(g_kegg,filename ='kegg_up_down_gsea.png')
}
### 2.GO database analysis
#go富集分析--耗费时间灰常长,很正常
if(F){
library(clusterProfiler)
#输入数据
gene_up= deg[deg$change == 'up','ENTREZID']
gene_down=deg[deg$change == 'down','ENTREZID']
gene_diff=c(gene_up,gene_down)
head(deg)
#**GO分析三大块**
#以下步骤耗时很长,实际运行时注意把if后面的括号里F改成T
if(F){
#细胞组分
ego_CC <- enrichGO(gene = gene_diff,
OrgDb= org.Hs.eg.db,
ont = "CC",
pAdjustMethod = "BH",
minGSSize = 1,
pvalueCutoff = 0.01,
qvalueCutoff = 0.01,
readable = TRUE)
#生物过程
ego_BP <- enrichGO(gene = gene_diff,
OrgDb= org.Hs.eg.db,
ont = "BP",
pAdjustMethod = "BH",
minGSSize = 1,
pvalueCutoff = 0.01,
qvalueCutoff = 0.01,
readable = TRUE)
#分子功能:
ego_MF <- enrichGO(gene = gene_diff,
OrgDb= org.Hs.eg.db,
ont = "MF",
pAdjustMethod = "BH",
minGSSize = 1,
pvalueCutoff = 0.01,
qvalueCutoff = 0.01,
readable = TRUE)
save(ego_CC,ego_BP,ego_MF,file = "ego_GPL6244.Rdata")
}
load(file = "ego_GPL6244.Rdata")
#**作图**
#第一种,条带图,按p值从小到大排序
barplot(ego_CC, showCategory=20,title="EnrichmentGO_CC")
barplot(ego_BP, showCategory=20,title="EnrichmentGO_BP")
#如果运行了没出图,就dev.new()
#第二种,点图,按富集数从大到小的
dotplot(ego_CC,title="EnrichmentGO_BP_dot")
#保存
pdf(file = "dotplot_GPL6244.pdf")
dotplot(ego_CC,title="EnrichmentGO_BP_dot")
dev.off()
}
#进阶方法,用循环来实现
if(F){
{
g_list=list(gene_up=gene_up,
gene_down=gene_down,
gene_diff=gene_diff)
if(T){
go_enrich_results <- lapply( g_list , function(gene) {
lapply( c('BP','MF','CC') , function(ont) {
cat(paste('Now process ',ont ))
ego <- enrichGO(gene = gene,
universe = gene_all,
OrgDb = org.Hs.eg.db,
ont = ont ,
pAdjustMethod = "BH",
pvalueCutoff = 0.99,
qvalueCutoff = 0.99,
readable = TRUE)
print( head(ego) )
return(ego)
})
})
save(go_enrich_results,file = 'go_enrich_results.Rdata')
}
load(file = 'go_enrich_results.Rdata')
n1= c('gene_up','gene_down','gene_diff')
n2= c('BP','MF','CC')
for (i in 1:3){
for (j in 1:3){
fn=paste0('dotplot_',n1[i],'_',n2[j],'.png')
cat(paste0(fn,'\n'))
png(fn,res=150,width = 1080)
print( dotplot(go_enrich_results[[i]][[j]] ))
dev.off()
}
}
}
}
——————————————————————————————————————
总结GEO分析流程:
总结代码流程: