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 数据获取策略

拿到数据不等于搞到数据。直接下载全库是懒人做法,但往往不是最优解。我建议按以下思路来:

  1. 明确你要的是“正样本”还是“负样本”
    • 正样本:已知药物-靶点有相互作用(比如Ki < 1μM)
    • 负样本:确认无相互作用(很难找,常用随机负采样)
  2. 确定活性阈值
    • 这个我吃过亏。曾经用IC50 < 10μM当阈值,结果引入了大量弱活性噪音。
    • 一般来说,Ki/IC50 < 1μM算强结合,< 10μM算中等。
  3. 考虑数据平衡性
    • 正样本往往稀少,负样本容易随机生成但噪声大。
    • 我自己的做法:正:负控制在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给的是文本。怎么办?统一标准。

我个人习惯的清洗流程:

  1. 统一ID体系
    • 药物:统一用PubChem CID
    • 靶点:统一用UniProt ID
    • 必要时构建ID映射表(ChEMBL→UniProt、DrugBank→PubChem)
  2. 去重
    • 同一个药物-靶点对在不同数据库里出现多次,取活性值中位数。
    • 注意:活性值单位要统一(比如全转成nM)。
  3. 过滤低质量记录
    • 去掉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 本章知识体系图

下面这张图概括了药物-靶点相互作用数据从获取到归纳的完整流程。画出来你就清楚了。

药物-靶点相互作用数据获取流程 药物-靶点相互作用数据获取流程 1. 选择公共数据库 DrugBank / ChEMBL / PubChem / STITCH / DGIdb 2. 制定获取策略 正/负样本 → 活性阈值 → 平衡比例 3. 数据获取方式 API在线查询(小规模) | 全量SQLite下载(大规模) 4. 数据整合与清洗 统一ID体系 → 去重 → 过滤低质记录 5. 输出标准格式 drug_id | target_id | activity

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

拿到这个数据,你就可以放心进入下一阶段——构建特征矩阵了。记住:数据准备虽然枯燥,但它是整个项目的基石。数据对了,模型跑起来你心里才有底。