第2章 生物医药数据源介绍:DrugBank、UniProt、KEGG等
做知识图谱,你得先搞清楚“数据从哪来”。
我刚入行那会,觉得只要会写代码、会搭图数据库就行。结果第一个项目就栽了跟头——图谱搭好了,但里面的实体和关系全对不上。为什么?因为数据源本身就有问题。
这一章,我带你过一遍生物医药领域最常用的几个公开数据库。你不必全记住,但得知道每个库的脾气、特长、以及我踩过的坑。
2.1 DrugBank:药物数据的“权威字典”
DrugBank(https://go.drugbank.com)是目前最全的开源药物与靶点数据库。它由加拿大阿尔伯塔大学维护,每年更新两次。说起这个库,我最开始用的时候真是又爱又恨。
2.1.1 核心特点
- 数据覆盖广:超过16,000种药物条目,包括FDA批准的小分子药物、生物药、以及实验阶段的候选化合物。
- 靶点信息丰富:每个药物条目都会列出靶点蛋白、作用机制、代谢酶、转运体等关联信息。
- 结构化程度高:提供XML和JSON格式下载,方便批量处理。
2.1.2 数据分层与典型字段
DrugBank的数据分三层:药物层、靶点层、交互层。我习惯用它的XML版本做知识图谱的实体抽取。
DrugBank XML结构示例(简化):
<drugbank xmlns="http://www.drugbank.ca">
<drug type="biotech">
<drugbank-id primary="true">DB00001</drugbank-id>
<name>Lepirudin</name>
<description>A recombinant hirudin...</description>
<targets>
<target>
<id>BE0000115</id>
<name>Thrombin</name>
<organism>Human</organism>
<actions>
<action>inhibitor</action>
</actions>
</target>
</targets>
</drug>
</drugbank>
我个人习惯把drugbank-id作为药物实体的唯一标识,把targets节点下的信息展开成“药物-抑制/激活-靶点”这样的关系。
我曾经在笔记本上跑一次解析用了4个小时还没出结果,后来改用
lxml.iterparse(),15分钟搞定。
2.1.3 常用字段映射表
| 概念 | XML路径 | 说明 | 图谱中角色 |
|---|---|---|---|
| 药物ID | /drugbank/drug/drugbank-id[@primary="true"] |
主键标识 | 实体ID |
| 药物名称 | /drugbank/drug/name |
通用名 | 实体标签 |
| 药物类型 | /drugbank/drug/@type |
small_molecule或biotech | 实体类别 |
| 靶点蛋白ID | /drugbank/drug/targets/target/id |
内部ID,需映射到UniProt | 关联节点标识 |
| 作用类型 | /drugbank/drug/targets/target/actions/action |
inhibitor, agonist, antagonist等 | 边类型/关系 |
/drugbank/drug/targets/target/polypeptide/@id找到UniProt的映射关系。我曾经直接拿DrugBank靶点ID去查UniProt,结果发现根本查不到,后来才意识到中间还有一个映射步骤。
2.2 UniProt:蛋白质信息的终极“户口本”
UniProt(Universal Protein Resource)是全世界最权威的蛋白质序列与功能数据库。说白了,你要查一个蛋白的基本信息,翻UniProt准没错。
它有两个核心子库:
- Swiss-Prot:人工校验,质量高,但覆盖少(约57万条)。
- TrEMBL:自动注释,数据量大(约2.5亿条),但可能有错误。
2.2.1 为什么知识图谱要用UniProt?
在药物靶点知识图谱中,蛋白是连接药物和基因的关键桥梁。DrugBank只说“这个药作用于某个靶点”,但靶点的序列、结构域、相关疾病、基因名称,都得靠UniProt补齐。
我建议你在图谱中直接把UniProt ID作为蛋白实体的主键。原因很简单:它是跨数据库的“通用语言”。
2.2.2 数据下载与解析
UniProt提供多种格式:
- XML:结构清晰,适合解析。
- Flat File(.dat):体积最小,但解析起来比较麻烦。
- JSON:逐渐成为主流,也推荐你使用。
UniProt JSON格式示例(核心字段):
{
"entryType": "UniProtKB_Swiss-Prot",
"primaryAccession": "P68871",
"uniProtkbId": "HBB_HUMAN",
"proteinDescription": {
"recommendedName": {
"fullName": {
"value": "Hemoglobin subunit beta"
}
}
},
"genes": [
{
"geneName": {
"value": "HBB"
}
}
],
"organism": {
"scientificName": "Homo sapiens",
"taxonId": 9606
}
}
嗯,这里要注意:UniProt的JSON API有流量限制。如果你要批量下载成千上万个蛋白,别用REST API一个个请求,去它的FTP服务器下完整数据集才是正道。
# 下载完整版Swiss-Prot的XML文件(2024年9月版)
wget ftp://ftp.uniprot.org/pub/databases/uniprot/current_release/knowledgebase/complete/uniprot_sprot.xml.gz
gunzip uniprot_sprot.xml.gz
<comment type="function">和<dbReference type="GO">这两块。前者描述蛋白功能,后者关联基因本体(GO),这些都是知识图谱中非常有价值的语义信息。
2.3 KEGG:通路与疾病网络的“导航图”
KEGG(Kyoto Encyclopedia of Genes and Genomes)是日本京都大学和东京大学联合维护的数据库。它的特色不是单个基因或蛋白,而是把生物过程看成“通路”。
我觉得KEGG最牛的地方在于:它把“基因”、“化合物”、“疾病”、“药物”串成了一张网。你想想看,这跟知识图谱的思维方式是不是天然契合?
2.3.1 核心子库
| 子库缩写 | 全称 | 包含内容 | 图谱用途 |
|---|---|---|---|
| KEGG PATHWAY | 通路数据库 | 540+条通路图 | 构建“基因-通路”关系 |
| KEGG DISEASE | 疾病数据库 | 疾病与基因、药物的关联 | 构建“疾病-靶点”关系 |
| KEGG DRUG | 药物数据库 | 日本批准药物+全球药物 | 补充DrugBank未覆盖的药物 |
| KEGG COMPOUND | 化合物数据库 | 小分子化合物信息 | 化学实体层 |
2.3.2 如何获取KEGG数据
KEGG提供REST风格的API,不需要KEY,但有并发限制。我习惯用它来查询“某个基因参与了哪些通路”。
# 获取基因hsa:3569(即IL6)参与的通路
curl "https://rest.kegg.jp/link/pathway/hsa:3569"
# 返回结果示例:
# hsa:3569 path:hsa04630 (JAK-STAT signaling pathway)
# hsa:3569 path:hsa05140 (Leishmaniasis)
# hsa:3569 path:hsa05142 (Chagas disease)
# hsa:3569 path:hsa05150 (Staphylococcus aureus infection)
# hsa:3569 path:hsa05160 (Hepatitis C)
# hsa:3569 path:hsa05161 (Hepatitis B)
# hsa:3569 path:hsa05162 (Measles)
# hsa:3569 path:hsa05164 (Influenza A)
# hsa:3569 path:hsa05168 (Herpes simplex infection)
# hsa:3569 path:hsa05202 (Transcriptional misregulation in cancer)
你看,一个IL6基因就关联了10条通路。这在知识图谱里就是“基因-参与-通路”的三元组关系。
2.3.3 KEGG DISEASE的独特价值
DrugBank虽然有适应症字段,但很多时候药理上“这个药能治这种病”并不等于“这种病的病因跟这个靶点有关”。KEGG DISEASE提供了更严谨的疾病-基因关联。
# 查看疾病D00045(Alzheimer disease)关联的基因
curl "https://rest.kegg.jp/link/genes/H00045"
# 结果包含已知的AD相关基因:
# hsa:3422 (IDUA)
# hsa:3426 (IFI16)
# hsa:351 (APP)
# hsa:5647 (PSEN1)
# hsa:5663 (PSEN2)
# hsa:5664 (PSENEN)
我曾经写了个并发脚本,一次性发了1000个请求,结果IP被KEGG封了24小时。嗯,从那以后我就老老实实加
sleep(1)了。
2.4 知识体系总览
这三个数据库各司其职,组合起来就能搭建一个初步的药物靶点知识图谱。我习惯把它们叫做“铁三角”:
- DrugBank:提供药物实体+药物-靶点关系
- UniProt:提供蛋白实体+功能描述+基因映射
- KEGG:提供通路、疾病与基因/药物的关联
SVG图展示这三者如何共同支撑起知识图谱的“实体-关系-语义”三层结构:
2.5 建图前的关键一步:ID映射
数据源介绍完了,有件事你必须心里有数:ID映射。
同一个蛋白,在DrugBank里是一个ID,在UniProt里是另一个ID,在KEGG里可能又是一个ID。你不把ID打通,图谱就是一张“断头路”。
我建议你在建图之前,先拉一张ID映射表:
# drugbank_uniprot_map.txt(示例)
DB00001 P68871
DB00002 P01019
DB00003 P00734
DB00004 P01375
UniProt官方提供了一个映射服务API,可以用来做批量转换:
# 使用UniProt ID Mapping API(POST请求)
curl -X POST "https://rest.uniprot.org/idmapping/run" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "from=DRUGBANK_DRUG_ACCESSION&to=UniProtKB&ids=DB00001,DB00002,DB00003,DB00004"
# 返回一个jobId,然后轮询结果:
curl "https://rest.uniprot.org/idmapping/results/{jobId}"
还记得我刚才说过的吗?ID映射是建图前最繁琐、但也最重要的预处理步骤。别偷懒,把这一步做扎实了,后面所有查询都不会报“节点不存在”的错误。
我在搭建第一个药物知识图谱时,就是因为忽略了这一步,导致图谱里出现了大量“孤儿节点”和“断头关系”,花了整整一周才补上。