4. 药物-靶点相互作用数据获取归纳总结
数据是药物重定位项目的燃料。没有高质量的相互作用数据,模型做得再花哨也是空中楼阁。我个人习惯把这步称为“淘金”,因为公共数据库里的确藏着金子,但沙子更多。这一章我们就来系统梳理:去哪淘?怎么淘?淘完怎么整理?
4.1 常见的公共数据库
说实话,我刚入行时觉得数据库嘛,随便找一个用就行。结果模型跑出来效果奇差,查了一圈才发现是用了过时的PubChem版本。你想想看,数据源头错了,后面的一切都是白费。
下面这几个库是我在项目中反复验证过的,靠谱。它们也是目前药物重定位领域的“标配”。
| 数据库 | 核心内容 | 更新频率 | 访问方式 |
|---|---|---|---|
| DrugBank | FDA批准药物+靶点,质量极高 | 每年1-2次 | 官网下载,需注册 |
| ChEMBL | 生物活性数据,覆盖面广 | 每季度 | 官网+API |
| PubChem | 化合物-靶点筛选结果 | 持续更新 | 官网+API |
| STITCH | 化学-蛋白质关联 | 停更(2016版仍可用) | 官网下载 |
| DGIdb | 药物-基因互作,临床导向 | 每半年 | 官网+API |
给我的建议: 如果你做的是已上市药物的重新定位,优先选DrugBank。如果要挖掘潜在活性分子,ChEMBL覆盖面更好。我在做肿瘤药物重定位项目时,就靠ChEMBL找到了几个冷门靶点的活性数据,效果很好。
小技巧: 下载数据前,先看看数据库的“Version History”。有些库的旧版本反而更稳定,改动少。比如ChEMBL 27版我就用得比较顺手,30版虽然数据量更大,但部分字段名改了,需要重新清洗。
4.2 数据获取策略
拿到数据不等于搞到数据。直接下载全库是懒人做法,但往往不是最优解。我建议按以下思路来:
- 明确你要的是“正样本”还是“负样本”
- 正样本:已知药物-靶点有相互作用(比如Ki < 1μM)
- 负样本:确认无相互作用(很难找,常用随机负采样)
- 确定活性阈值
- 这个我吃过亏。曾经用IC50 < 10μM当阈值,结果引入了大量弱活性噪音。
- 一般来说,Ki/IC50 < 1μM算强结合,< 10μM算中等。
- 考虑数据平衡性
- 正样本往往稀少,负样本容易随机生成但噪声大。
- 我自己的做法:正:负控制在1:5到1:10之间。
4.3 实操:从ChEMBL拉取数据
ChEMBL提供了官方API,我用Python的chembl_webresource_client库来拉数据。为什么用它?因为可以精细控制查询条件,不会把整个数据库拖下来。我的硬盘曾经被几十GB的JSON文件撑爆过,嗯,那是年轻时的教训。
pip install chembl_webresource_client
下面是一个典型的查询:获取某个靶点(比如EGFR)的所有药物相互作用数据。
from chembl_webresource_client.new_client import new_client
# 初始化客户端
target = new_client.target
activity = new_client.activity
# 根据靶点名查找
targets = target.search('EGFR')
target_id = targets[0]['target_chembl_id']
# 获取该靶点的所有活性数据
activities = activity.filter(target_chembl_id=target_id)
.filter(standard_type__in=['IC50', 'Ki'])
.filter(standard_relation='=')
# 转为DataFrame
import pandas as pd
df = pd.DataFrame.from_records(activities)
注意: API有速率限制。ChEMBL默认每分钟最多1000次请求。你写循环拉取大量数据时,记得加个time.sleep(0.1)。我就曾经因为在循环里没加延时,被临时封了IP,等了半小时才恢复。
如果你的数据量很大,不建议用API。直接下载全量SQLite文件更靠谱。
# 下载ChEMBL SQLite(约5GB)
wget ftp://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb/latest/chembl_30.db.gz
gunzip chembl_30.db.gz
# 用Python读取
import sqlite3
conn = sqlite3.connect('chembl_30.db')
query = """
SELECT md.chembl_id, td.chembl_id, act.standard_value, act.standard_type
FROM activities act
JOIN molecule_dictionary md ON act.molregno = md.molregno
JOIN target_dictionary td ON act.td_chembl_id = td.chembl_id
WHERE act.standard_type = 'IC50' AND act.standard_relation = '='
"""
df = pd.read_sql_query(query, conn)
4.4 数据整合与清洗
数据拿回来了,但不同库的格式千差万别。DrugBank给的是XML,ChEMBL给的是表格,STITCH给的是文本。怎么办?统一标准。
我个人习惯的清洗流程:
- 统一ID体系
- 药物:统一用PubChem CID
- 靶点:统一用UniProt ID
- 必要时构建ID映射表(ChEMBL→UniProt、DrugBank→PubChem)
- 去重
- 同一个药物-靶点对在不同数据库里出现多次,取活性值中位数。
- 注意:活性值单位要统一(比如全转成nM)。
- 过滤低质量记录
- 去掉
standard_relation为'>'或'<'的记录,只保留精确值'='。 - 去掉缺失靶点或药物的记录。
- 去掉
# 示例:清洗后的标准格式
# drug_id, target_id, activity_value_nM, confidence_score
CID0000001, P00533, 12.5, 0.95
CID0000002, P00533, 150.0, 0.88
CID0000003, P01375, 800.0, 0.72
4.5 本章知识体系图
下面这张图概括了药物-靶点相互作用数据从获取到归纳的完整流程。画出来你就清楚了。
4.6 避坑指南
有些坑我踩过,你们就别踩了。
防坑1:负样本别瞎造
我曾经在STITCH数据里看到很多“未确认”的相互作用,就单纯把它们当负样本。结果模型学到的全是假阴性信号。正确做法:只用实验确认的“无相互作用”数据,或者用结构相似性筛选后的负样本。
防坑2:批次效应
不同实验室测出的同一药物-靶点Ki值能差10倍。你想想看,跨库合并数据时不处理这个,模型训练出来就废了。我的经验:按数据来源(数据库)做Z-score标准化,或者只保留置信度高的来源。
我的习惯: 做完清洗后,我会随机挑20-30条药物-靶点对,去PubMed验证对应的文献。这一步虽然耗时,但能暴露出大量数据质量问题。有一次我就发现某个数据库把“药物A抑制靶点B”的结论标反了。
4.7 最终输出格式
经过上述步骤,你应该得到一个干净的表格。我一般存成CSV或Parquet格式,方便后续模型使用。
# 最终数据示例(前5行)
drug_pubchem_id, target_uniprot, activity_nM, source, confidence
CID_2244, P00533, 1.2, chembl, 0.95
CID_2244, P04626, 850.0, drugbank, 0.88
CID_5280343, P01375, 450.0, chembl, 0.72
CID_60823, P04637, 0.8, pubchem, 0.91
CID_2519, P15121, 320.0, stitc, 0.65
拿到这个数据,你就可以放心进入下一阶段——构建特征矩阵了。记住:数据准备虽然枯燥,但它是整个项目的基石。数据对了,模型跑起来你心里才有底。