以下内容全部来自于此文章https://www.jianshu.com/p/f2e4dbaae719作者:Bioinfo鱼
生信 | 构建物种的OrgDb
写在前面
- 本文主要参考生信小白2018与多啦A梦的时光机的,但由于EggNOG(v5.0)数据库与eggnog-mapper(v2.1.3)更新后,修改了输出文件的格式,因此他们二人写的脚本会出现一些问题,但R学的好的话完全可以克服,我保留了他们的大部分源码并进行了debug,优化了一些步骤,供大家参考。
注意:完成下面的步骤至少需要~40GB运行内存与~50GB的存储空间,因此没有服务器的同学不要轻易尝试
1. 使用eggnog-mapper生成注释文件
- 以下代码在Linux中运行
1.1. 下载eggnog-mapper软件
- conda上可以直接下载了 conda install eggnog-mapper
conda install eggnog-mapper
1.2. 下载EggNOG数据库
- 下载链接:http://eggnog5.embl.de/download/
- 请严格按照图片操作。
注意:一定要放到eggnog-mapper软件目录下的data文件夹中,使用conda装的放到类似的conda路径下面:其中dna为我的环境变量,在这个/site-packages文件夹中是没有/data文件夹的,我是自己创建的文件夹。
/home/data/t040331/anaconda3/envs/dna/lib/python3.10/data/
其中需要更改的就是你安装miniconda的路径以及conda环境的名称。因为我是安装python3环境中的,所以路径如上。
wget http://eggnog5.embl.de/download/emapperdb-5.0.2/eggnog.db.gz
wget http://eggnog5.embl.de/download/emapperdb-5.0.2/eggnog_proteins.dmnd.gz
###下载所需要的文件
- 使用gunzip解压
gunzip eggnog.db.gz eggnog.proteins.dmnd.gz
1.3. 运行eggnog-mapper
注意:蛋白文件的中基因名必须要和你以后富集分析的基因名格式相同,如果不同,后面的操作都是徒劳,千万注意。
emapper.py -i Ahypogaea_530_v1.0.protein.fa -o Ahypogaea_530_v1.0 -d euk --cpu 40 --dbmem
-i:输入的蛋白组序列文件,请自行下载你物种的pep序列文件,并将其中的ID换为你常用的ID,不然到时候根据ID富集不到也就白忙活了。
-o:输出文件的前缀,后缀会自动补充为.emapper.annotations
-m:默认就是diamond,因此不用指定。
--dbmem:将数据库全部存入运行内存,极大提高运行速度,但特别吃运存,大约要45GB的运行空间。
--cpu:使用的线程数
--override:可以覆盖原有的文件,多次尝试的时候可以加上
-d: 比对数据库的类型,作者给了euk(真核), bact(细菌), arch(古菌)三大类。虽然大类更全,但有顾虑就是植物动物微生物乱匹配,因此推荐使用--tax_scope
--tax_scope: 有以下参数可以选择。
如小鼠可选Eukaryota下面的Chordata(脊椎动物),即emapper.py -i mm39.pep.fa -o mm39 --tax_scope Chordata
如拟南芥可选Eukaryota下面的Viridiplantae(绿色植物),即emapper.py -i tair.pep.fa -o tair --tax_scope Viridiplantae
再比如想选择多个,那么就把他们写入到文件中,然后入读,即emapper.py -i tair.pep.fa -o tair --tax_scope ./example.txt
1.4.运行结果
运行结束后,eggnog-mapper会生成三个文件,以花生为例:
-
Ahypogaea_530_v1.0.hmm_hits
: 记录每个用于搜索序列对应的所有的显著性的eggNOG Orthologous Groups(OG). 所有标记为"-"则表明该序列未找到可能的OG-
Ahypogaea_530_v1.0.seed_orthologs
: 记录每个用于搜索序列对的的最佳的OG,也就是Ahypogaea_530_v1.0.hmm_hits里选择得分最高的结果。之后会从eggNOG中提取更精细的直系同源关系(orthology relationships) -
Ahypogaea_530_v1.0.emapper.annotations
: 该文件提供了最终的注释结果,也是我们后续构建OrgDb的文件
它一共有21列,列名如下:
query:检索的基因名或者其他ID,就是提供蛋白组序列文件中的ID,所以这个ID和以后做GO/KEGG分析的ID要相同,不然就没办法做了,已经说了好多次了。
seed_ortholog
evalue
score
eggNOG_OGs
max_annot_lvl
COG_category
Description
Preferred_name:预测的基因名,特别类似AP2有含义的基因名,可以直接在NCBI 的 Gene数据库中查看,一般是其他物种确定了功能的基因名
GOs:推测的GO的词条
EC
KEGG_ko:推测的KEGG KO词条
KEGG_Pathway:该条目显示的是K中包含的Ko以及map,没用,后面我们会自己生成
KEGG_Module
KEGG_Reaction
KEGG_rclass
BRITE
KEGG_TC
CAZy
BiGG_Reaction:BiGG
PFAMs
-
1.5. 处理数据
- 首先删掉【Ahypogaea_530_v1.0.emapper.annotations】开头与末尾没用的行和表头的#即可,然后使用awk提取需要的列
- 重输出为【Ahypogaea_530_v1.0.annotations】
id=Ahypogaea_530_v1.0 #刚才的前缀
sed '/^##/d' ${id}.emapper.annotations| sed 's/#//g'| awk -vFS="\t" -vOFS="\t" '{print $1,$9,$10,$12}' > ${id}.annotations
小插曲:在这里我生成的文件是“-Ahypogaea_530_v1.0.emapper.annotations”文件名多了一个‘-’所以在运行sed命令时被识别成了-A命令,所以一直报错,之后将‘-’删除后就正常了
- 然后就可以使用【Ahypogaea_530_v1.0.annotations】开始在R中构建OrgDb了
2. 构建OrgDb
- 以下代码在R中运行
2.1. 安装并导入所需R包
setwd("D:/桌面/KEGG/new_KEGG")
BiocManager::install("dplyr",force = TRUE)
BiocManager::install("stringr",force = TRUE)
BiocManager::install("jsonlite",force = TRUE)
BiocManager::install("AnnotationForge")
library(dplyr)
library(stringr)
library(jsonlite)
library(AnnotationForge)
options(stringsAsFactors = F)#设置一下options
2.2. 读入生成的annotations文件
emapper <- read.table("Ahypogaea_530_v1.0.annotations",header = TRUE,sep = "\t",quote = "")
#将空值替换为NA,方便后续使用na.omit()函数提出没有注释到的行
emapper[emapper==""]<-NA
2.3. 提取GO信息
- 把emapper中的【query】列、【Preferred_name】列【GOs】列提取出来(其中【%>%】相当于linux中的管道符【|】)
# library(dplyr)
gene_info <- emapper %>% dplyr::select(GID = query, GENENAME = Preferred_name) %>% na.omit()
gos <- emapper %>% dplyr::select(query, GOs) %>% na.omit()
- 构建一个空的【gene2go】数据框,为后面填充数据用
gene2go = data.frame(GID = character(),
GO = character(),
EVIDENCE = character())
- 对【gene2go】空数据框进行填充。
gos_list <- function(x){
the_gos <- str_split(x[2], ",", simplify = FALSE)[[1]]
df_temp <- data.frame(GID = rep(x[1], length(the_gos)),
GO = the_gos,
EVIDENCE = rep("IEA", length(the_gos)))
return(df_temp)
}
gene2gol <- apply(as.matrix(gos),1,gos_list)
gene2gol_df <- do.call(rbind.data.frame, gene2gol)
gene2go <- gene2gol_df
gene2go$GO[gene2go$GO=="-"]<-NA
gene2go<-na.omit(gene2go)
- 循环的作用简单来说就单行变多行,举例如下:
# query1 GO:XXXXXX1
#query1 GO:XXXXXX1,GO:XXXXXX2,GO:XXXXXX3 => query1 GO:XXXXXX2
# query1 GO:XXXXXX3
2.4. 同理,提取KEGG信息
- 把emapper中的query列、KEGG_ko列提取出来
gene2ko <- emapper %>% dplyr::select(GID = query, Ko = KEGG_ko)
gene2ko$Ko[gene2ko$Ko=="-"]<-NA
gene2ko<-na.omit(gene2ko)
gene2kol <- apply(as.matrix(gene2ko),1,gos_list)
gene2kol_df <- do.call(rbind.data.frame, gene2kol)
gene2ko <- gene2kol_df[,1:2]
colnames(gene2ko) <- c("GID","Ko")
gene2ko$Ko <- gsub("ko:","",gene2ko$Ko)
下载KO的json文件并【放到当前工作目录下】,下载地址:https://www.genome.jp/kegg-bin/get_htext?ko00001
- 定义函数,不用管是啥直接跑,其中只用到了下载的【ko00001.json】文件,所以可以放心跑
# library(jsonlite)
# 下面的json = "ko00001.json",如果你下载到其他地方,记得加上路径
update_kegg <- function(json = "ko00001.json") {
pathway2name <- tibble(Pathway = character(), Name = character())
ko2pathway <- tibble(Ko = character(), Pathway = character())
kegg <- fromJSON(json)
for (a in seq_along(kegg[["children"]][["children"]])) {
A <- kegg[["children"]][["name"]][[a]]
for (b in seq_along(kegg[["children"]][["children"]][[a]][["children"]])) {
B <- kegg[["children"]][["children"]][[a]][["name"]][[b]]
for (c in seq_along(kegg[["children"]][["children"]][[a]][["children"]][[b]][["children"]])) {
pathway_info <- kegg[["children"]][["children"]][[a]][["children"]][[b]][["name"]][[c]]
pathway_id <- str_match(pathway_info, "ko[0-9]{5}")[1]
pathway_name <- str_replace(pathway_info, " \\[PATH:ko[0-9]{5}\\]", "") %>% str_replace("[0-9]{5} ", "")
pathway2name <- rbind(pathway2name, tibble(Pathway = pathway_id, Name = pathway_name))
kos_info <- kegg[["children"]][["children"]][[a]][["children"]][[b]][["children"]][[c]][["name"]]
kos <- str_match(kos_info, "K[0-9]*")[,1]
ko2pathway <- rbind(ko2pathway, tibble(Ko = kos, Pathway = rep(pathway_id, length(kos))))}}}
save(pathway2name, ko2pathway, file = "kegg_info.RData")}
# 调用函数后在本地创建kegg_info.RData文件,以后只需要载入 "kegg_info.RData"即可
update_kegg()
# 载入kegg_info.RData文件
load(file = "kegg_info.RData")
- 根据gene2ko中的Ko信息将ko2pathway中的Pathway列提取出来
gene2pathway <- gene2ko %>% left_join(ko2pathway, by = "Ko") %>% dplyr::select(GID, Pathway) %>% na.omit()
2.5. 获取物种信息
首先在NCBI上查询你物种的相关信息,网址:https://www.ncbi.nlm.nih.gov/taxonomy
比如拟南芥Arabidopsis thaliana
# tax_id = "3702"
# genus = "Arabidopsis"
# species = "thaliana"
其实,都可以随便填写,不会影响建库结果,只会影响你输出文件的名字,像个性化输出名字就自定义
可以去重,以防万一,或者等下面报错提示去重再去跑代码也行。原理是,makeOrgPackage不允许有重复的行,因此需要删除,除了gene2pathway可能有重复的行,其他几乎不可能有重复的情况。
# gene2go <- unique(gene2go)
# gene2go <- gene2go[!duplicated(gene2go),]
# gene2ko <- gene2ko[!duplicated(gene2ko),]
# gene2pathway <- gene2pathway[!duplicated(gene2pathway),]
# gene_info <- gene_info[!duplicated(gene_info),]
2.6. 构建OrgDb
makeOrgPackage(gene_info=gene_info,
go=gene2go,
ko=gene2ko,
pathway=gene2pathway,
version="1.38.0 ", #版本,使用?makeOrgPackage,拉到最下面查看
maintainer = "your name ", #修改为你的名字和邮箱
author = "your name ", #修改为你的名字和邮箱
outputDir = "D:/桌面/KEGG/new_KEGG", #输出文件位置
tax_id=tax_id, #你在NCBI上查并定义的id
genus=genus, #你在NCBI上查并定义的属名
species=species, #你在NCBI上查并定义的种名
goTable="go")
- 构建成功后会在当前路径下生成一个【文件夹】,名字形如【org.XXX.eg.db】(其中XXX的构成为你定义的genus的大写首字母+species名,如小鼠是Mmusculus,人是Hsapiens,拟南芥是Athaliana)
3. 导入OrgDb库
install.packages("org.Ahypogaea.eg.db", repos=NULL, type="source")
library(org.Ahypogaea.eg.db)
# 查看所有列的信息
columns(org.Ahypogaea.eg.db)
# 查看所有基因
keys(org.Ahypogaea.eg.db)
# 查看特定基因的信息
# library(dplyr)
select(org.Ahypogaea.eg.db, keys = "arahy.Tifrunner.gnm1.ann1.K8W5NT.1", columns = c("GO"))
4. 导出背景文件
- 因为我们在后面进行kegg分析的时候需要背景文件,因此为了方便即可导出
pathway2name
和pathway2gene
# 做一些常规格式化
pathway2name$Name <- gsub(" \\[BR:ko[0-9]{5}\\]", "",pathway2name$Name)
pathway2name<- na.omit(pathway2name)
pathway2gene <-gene2pathway[, c("Pathway","GID")]
# 输出
write.table(pathway2name,file = "./pathway2name", sep = "\t", quote = F, row.names = F)
write.table(pathway2gene,file = "./pathway2gene", sep = "\t", quote = F, row.names = F)
5. 使用clusterProfiler富集分析
5.1 KEGG富集分析(不需要OrgDB)
library(clusterProfiler)
# 每次只需导入下面两个文件即可
pathway2gene <- read.table("./pathway2gene",header = T,sep = "\t")
pathway2name <- read.table("./pathway2name",header = T,sep = "\t")
# 导入你鉴定到的差异基因列表,并转化为向量
gene <- read.csv("gene_list.csv")
gene_list <- gene[,1]
# KEGG pathway 富集
ekp <- enricher(gene_list,
TERM2GENE = pathway2gene,
TERM2NAME = pathway2name,
pvalueCutoff = 1, # 表示全部保留,可以设为0.05作为阈值
qvalueCutoff = 1, # 表示全部保留,可以设为0.05作为阈值
pAdjustMethod = "BH",
minGSSize = 1)
dotplot(ekp)
5.2 GO富集分析(需要OrgDB)
library(org.Ahypogaea.eg.db)
ego <- enrichGO(gene=gene_list,
OrgDb=org.Ahypogaea.eg.db,
keyType="GID",
ont="ALL", #CC/BP/MF可选
qvalueCutoff = 0.05,
pvalueCutoff =0.05)
dotplot(ego)
# 无论是ekp还是ego都可以选择将数据导出,然后可以自己使用ggplot画
ego_results<-as.data.frame(ego)
write.table(ego_results, file = "D:/桌面/KEGG/new_KEGG/ego_results.txt", quote = F)