第2章:药物数据来源——我们到底要从哪儿挖数据?
做知识图谱,第一步永远不是写代码。而是搞明白——数据在哪儿?
很多人觉得数据就是拿来就用的,其实没那么简单。药物领域的数据源非常分散,格式各异,质量也参差不齐。我刚开始做这个项目时,天真地以为一个DrugBank就够了。结果你猜怎么着?做了两周才发现,很多药物的靶点信息在DrugBank里是缺失的,得去PubChem和ChEMBL交叉补全。嗯,从那以后我就养成了一个习惯:开工之前,先把数据源摸清楚。
这一章,我们就来聊聊药物知识图谱的四大数据来源。说白了,就是你的“数据食谱”。
2.1 数据来源全景
先给你一张全景图。药物知识图谱的数据源可以分成四类:
- 公开药物数据库:结构化的、经过人工审核的高质量数据。比如DrugBank、PubChem、ChEMBL。
- 药物标签数据:官方审批文件,如FDA标签、EMA说明书。信息权威但格式不统一。
- 科研文献数据:海量的非结构化文本,但包含最新的发现。需要NLP技术抽取。
- 其他辅助数据:临床试验注册信息、基因表达数据、疾病本体等。
这几类数据,各有各的脾气。你没法用同一把钥匙开所有的锁。下面我一个个说。
核心观点:药物知识图谱的数据源选择,直接影响图谱的完整性和准确性。不要只依赖单一数据源,多源融合是常态。
为了让你看得更清楚,我画了一张数据来源结构图。所有数据最终汇聚到统一的融合管道。
这张图讲的是数据融合的基本流程。别急,后面我会细讲每个数据源怎么接入。
2.2 公开药物数据库:你的主力粮仓
先说结构化数据。这类数据最干净,能直接解析成表格或JSON。我个人的经验是,先从这类数据下手,打好骨架。
2.2.1 DrugBank
DrugBank是目前最全的药物数据库之一。由加拿大阿尔伯塔大学维护。它包含药物的化学结构、靶点、代谢酶、转运体、相互作用等。数据质量很高,因为是专家审核的。
你有两种方式拿到数据:
- 在线查询:通过官网页面搜索,适合小规模调研。
- 数据导出:申请学术使用许可,可获得完整的XML或JSON导出文件。
我记得最早一次用DrugBank数据时,下载下来的XML文件有几百兆。结构复杂,嵌套层数多。你需要耐心解析。这里给一个简单的XML解析思路:
<drug type="small molecule">
<drugbank-id>DB00001</drugbank-id>
<name>Aspirin</name>
<description>...</description>
<targets>
<target>
<id>BE00001</id>
<name>Prostaglandin G/H synthase 1</name>
<organism>Human</organism>
<action>inhibitor</action>
</target>
</targets>
</drug>
技巧:解析DrugBank的XML时,建议使用流式解析器(比如Python的iterparse),不要一次性加载整个文件到内存。我当年用dom解析吃掉了8G内存,你想想看。
2.2.2 PubChem
PubChem是美国国立卫生研究院(NIH)维护的。它更侧重于小分子化学结构。也就是说,如果你需要药物的SMILES表达式、分子量、理化性质,PubChem是首选。
PubChem提供了强大的RESTful API。你可以通过化合物CID直接查。我个人的习惯是,先用DrugBank拿到药物CID,再去PubChem补全化学性质。
GET https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/2244/JSON
返回JSON示例:
{
"PC_Compounds": [{
"id": {"id": {"cid": 2244}},
"props": [
{"urn": {"label": "Molecular Weight"}, "value": {"sval": "180.16"}},
{"urn": {"label": "SMILES"}, "value": {"sval": "CC(=O)Oc1ccccc1C(=O)O"}}
]
}]
}
调用这个API时,注意频次限制。我曾经压得太狠,直接被封了半小时。后来加了高速缓存,同一个CID只查一次。
2.2.3 ChEMBL
ChEMBL由欧洲生物信息学研究所(EBI)维护。它的特色是——药物活性数据。也就是说,某个化合物对哪个靶点有怎样的活性(IC50、Ki等),在ChEMBL里很全。
ChEMBL也提供API,但它的数据还可以通过SDF或SQLite文件下载。我个人倾向于用SQLite版本,直接写SQL查询,效率高很多。
-- 查询阿司匹林相关的靶点活性数据
SELECT md.chembl_id, td.pref_name AS target_name, ad.standard_value, ad.standard_type
FROM molecule_dictionary md
JOIN activities ad ON md.molregno = ad.molregno
JOIN target_dictionary td ON ad.tid = td.tid
WHERE md.pref_name = 'ASPIRIN';
注意:ChEMBL的数据版本更新较快(每年1~2个版本)。不同版本之间,同一个分子的ChEMBL ID可能会变。所以做项目时,一定要固定一个数据版本,并在文档里记录。
2.3 药物标签数据:权威但难啃的骨头
公开数据库虽好,但有些信息是缺失的。比如药物的不良反应详情、特殊人群用药、上市后变更等。这些信息藏在药物标签里。
FDA提供了一个下载服务——DailyMed。你可以通过它拿到所有已审批药物的结构化标签(SPL格式)。说白了,就是XML格式的说明书。
这里有个坑。我踩过。SPL文件虽然结构化,但不同厂家提交的标签,段落命名和层级不一致。比如“不良反应”这个章节,有的用“ADVERSE REACTIONS”,有的用“ADVERSE EFFECTS”。你需要做一个章节名称的归一化映射表。
<section>
<code code="34090-1" codeSystem="2.16.840.1.113883.6.1" displayName="ADVERSE REACTIONS"/>
<title>Adverse Reactions</title>
<text>The most common adverse reactions include nausea, vomiting, and diarrhea.</text>
</section>
我曾经为了解析6000个FDA标签,写了一个专门的SPL解析器。花了整整一周。后来发现,有一些开源工具可以辅助,比如PySPL。所以我的建议是:不要重复造轮子,先找找有没有现成的工具。
2.4 科研文献数据:价值与噪音并存
最后说说文献。药物知识图谱里,对最新的药物-靶点-疾病关联,通常文献里最先报道。但文献是纯文本,没法直接用。
你需要做文本挖掘。最常见的思路是:
- 下载PubMed的摘要数据(XML格式,免费)。
- 用自然语言处理(NLP)工具识别药物和靶点实体。
- 抽取实体之间的关系(比如“激活”、“抑制”)。
举个例子,一句文献摘要:
"Aspirin inhibits the activity of cyclooxygenase-1, thereby reducing prostaglandin synthesis."
用命名实体识别(NER)抽取出:
- 药物:Aspirin
- 靶点:cyclooxygenase-1
- 关系:inhibits (抑制)
避坑指南:文献数据的噪声很高。同一个药物可能有不同的别名(比如“Aspirin”和“Acetylsalicylic acid”)。你还需要做实体对齐。我见过有人直接拿文献数据建图,结果同一个药物出现了十几个节点。嗯,这就尴尬了。
2.5 数据融合与预处理:让拼图严丝合缝
数据源都讲完了。你手里可能握着四个不同格式的数据集:DrugBank的XML、PubChem的JSON、ChEMBL的SQLite、FDA标签的SPL。
怎么把它们揉在一起?
我的做法是三步:
- 统一ID映射:给每个药物一个唯一的内部ID。然后建立外部ID映射表(DrugBank ID ↔ PubChem CID ↔ ChEMBL ID)。
- 属性标准化:同一个属性,不同数据源的命名不同。比如“分子量”,DrugBank叫“molecular_weight”,PubChem叫“Molecular Weight”。统一成你的图谱schema里的标准属性名。
- 冲突消解:当多个数据源对一个属性的值不一致时怎么办?我个人的规则是:权威性优先(DrugBank > ChEMBL > PubChem),但保留来源信息。