药物图谱数据来源:公开数据库
这一章我们聊聊数据从哪来。你可能以为做药物图谱对齐,最难的是算法本身。其实我这些年踩过最多的坑,反而是数据源的问题。数据不好,再牛的模型也白搭。
公开数据库是药物图谱的根基。我个人习惯把它们分成三大类:药物专库、化学-基因交叉库、副作用信息库。每个库都有自己的脾气,摸透了才能用好。
DrugBank:药物数据的“维基百科”
DrugBank 是我最先接触的数据库。说白了,它就是药物领域的百科全书。不仅有药物的化学结构,还包含了靶点、代谢酶、转运体、药物相互作用等核心信息。
我刚开始做图谱时,第一个想到的就是它。为什么?因为它够全,够权威。截至最新版,DrugBank 收录了超过 15000 种药物条目,其中 FDA 批准的就有 2600 多种。
它的核心字段很清晰:
- DrugBank ID:唯一标识,比如 DB00001
- 通用名/商品名:用于名称对齐
- 靶点列表:蛋白质靶点信息
- 药物相互作用:DDI 数据
- ATC 编码:解剖学治疗学分类
获取 DrugBank 数据的一个 API 示例:
GET https://api.drugbank.com/drugs/DB00001
Authorization: Bearer YOUR_API_KEY
Response (简化):
{
"drugbank_id": "DB00001",
"name": "Leptirudin",
"type": "biotech",
"targets": [
{
"id": "BE00001",
"name": "Thrombin",
"action": "inhibitor"
}
],
"drug_interactions": [...]
}
CTD:化学-基因-疾病的桥梁
CTD(Comparative Toxicogenomics Database) 是另一个宝藏。它不像 DrugBank 那样只关注药物本身,而是把化学物质、基因和疾病串起来了。
你想想看,药物图谱不仅要对齐药物名,还得对齐基因名、疾病名。CTD 在这方面的数据,是我见过最完整的。它收录了超过 200 万条化学-基因相互作用,以及 100 多万条化学-疾病关联。
CTD 的核心数据表:
| 数据类别 | 字段说明 | 对齐价值 |
|---|---|---|
| Chemical-Gene Interactions | 化学物质、基因符号、相互作用类型 | 帮助对齐化学名和基因名 |
| Chemical-Disease Associations | 化学物质、疾病名、关联证据 | 对齐化学名和疾病名 |
| Gene-Disease Associations | 基因符号、疾病名、关联类型 | 对齐基因名和疾病名 |
CTD 的数据下载下来是 TSV 格式,解析起来很方便。我曾经用它做过一个化学物质-疾病关系的实体对齐任务,效果出奇得好。因为它的数据是人工标注的,质量很高。
SIDER:药物副作用的“信号灯”
SIDER(Side Effect Resource) 是专门做药物副作用的数据库。它从公开的 FDA 标签和文献中提取副作用信息,覆盖面相当广。
数据拿到手就完事了?其实不是。SIDER 的数据有个特点:副作用名称来自 MedDRA 术语库,而药物名来自 PubChem。这就涉及两个词表的对齐。
我在做这个库的时候,踩过一个坑:SIDER 里同一个药物可能有多个名称变体。比如“阿司匹林”可能是“Aspirin”,也可能是“Acetylsalicylic acid”。如果不做实体对齐,图谱里就会有重复节点。
SIDER 的数据结构:
# SIDER 药物-副作用关联数据示例
drug_name side_effect frequency
Aspirin Nausea frequent
Aspirin Gastric ulcer rare
Ibuprofen Headache common
Ibuprofen Dizziness uncommon
其他值得关注的公开数据库
除了上面三个,还有几个库我觉得很有用:
- UniProt/Swiss-Prot:蛋白质靶点数据,用于对齐基因名和蛋白质名
- PharmGKB:药物基因组学数据,包含基因型-药物反应关联
- DGIdb:药物-基因相互作用数据库,整合了多种来源
- PubChem:化合物数据库,提供化学结构的统一标识
常见数据挑战和应对思路
数据多了,问题也来了。我罗列几个常见情况:
- 命名不统一:同一个药物在不同库可能用不同名字。比如“扑热息痛”在 DrugBank 叫“Acetaminophen”,在 SIDER 叫“Paracetamol”。
- ID 映射缺失:有些库没有提供跨库 ID 映射,需要手动桥接。
- 数据版本不一致:不同库的更新频率不同,对齐时可能碰到过期数据。
- 冗余和冲突:同一个关系在不同库里有不同的描述方式。
嗯,遇到这些问题别慌。我的建议是先做一次全量 ID 映射,把 DrugBank ID、PubChem CID、ChEBI ID、UniProt ID 这些统一起来。然后基于映射结果去去重。
# 伪代码:ID 映射流程
mapping_dict = {}
for drug in drugbank_data:
pubchem_cid = lookup_pubchem(drug.name)
mapping_dict[drug.drugbank_id] = pubchem_cid
mapping_dict[drug.name] = pubchem_cid
# 统一后,实体对齐就简单多了
这张图展示了数据源和下游任务的关系。虚线箭头是提醒你:数据拿过来不是直接用的,中间得做实体对齐这把关键工序。
实战:数据预处理流程
最后,我分享一下我的标准预处理流程。不管用哪个库,这个流程基本通用:
- 下载原始数据:从各数据库官网获取最新版本
- 提取核心字段:只保留对齐所需的最小字段集
- ID 标准化:统一使用 PubChem CID 或 DrugBank ID 作为主键
- 名称归一化:统一大小写、去除空格、处理同义词
- 跨库关联:基于 ID 映射表,把不同源的数据串起来
- 质量校验:检查是否有缺失、重复、冲突的数据
这个流程听起来简单,但每个步骤都有坑。尤其是名称归一化这一步,我曾经因为没处理好连字符导致上千条记录匹配失败。所以,细节决定成败。