药物与靶点资源:三大数据库实战

做药物靶点关系抽取,第一件事不是写代码,而是搞清楚数据从哪来。我当年刚入行时,以为爬个PubMed就能搞定,结果发现那是个大坑——实体识别搞到崩溃,关系标注更是噩梦。后来老同事告诉我:“你先把这三家数据库啃透,剩下的都是手艺活。”这三家就是DrugBank、UniProt和CTD。

说白了,这三个数据库构成了药物-靶点-疾病关系的黄金三角。下面我按自己的使用习惯,一个个讲清楚。

药物-靶点资源黄金三角 DrugBank 药物结构·靶点·机制 UniProt 蛋白序列·功能·分类 CTD 化学-基因-疾病网络 靶点名→蛋白ID 药物→化学 靶点→基因 关系抽取核心数据集 药物-靶点-疾病三元组

DrugBank:药物数据的顶梁柱

如果你只能用一个药物数据库,那就是DrugBank。它不光告诉你药物化学结构,还给出了已知靶点、作用机制、代谢路径。我个人习惯先从DrugBank里拉一份药物-靶点列表,再去做深度的关系挖掘。

举个例子,你要查阿司匹林的靶点。在DrugBank里搜DB00945,返回的信息里直接有靶点蛋白的UniProt ID。怎么拿到这些数据?官方提供REST API,也可以下载XML或JSON格式的完整库。我常用的是API方式,省得本地存一大坨文件。

# 获取DrugBank中某个药物的基本信息(需申请API Key)
import requests

api_key = "YOUR_DB_API_KEY"
drug_id = "DB00945"  # 阿司匹林
url = f"https://api.drugbank.com/v1/drugs/{drug_id}"
headers = {"Authorization": f"Bearer {api_key}"}
response = requests.get(url, headers=headers)
data = response.json()

# 打印靶点UniProt ID
for target in data["drug"]["targets"]:
    print(target["uniprot_id"])
提示:DrugBank的API Key需要去官网申请,学术用户免费。建议申请后把Key存在环境变量里,别硬编码。

除了API,DrugBank的Excel导出也很好用。下载drugbank_all_drugs.csv,直接用Pandas读入,做简单的表格处理。在项目早期验证思路时,这个方式最快。

UniProt:靶点蛋白的终极参考

有了DrugBank给的UniProt ID,接下来就要去UniProt查蛋白的详细信息。UniProt把蛋白数据分成两个层:Swiss-Prot(人工校验,高质量)和TrEMBL(自动注释,量大但杂)。做药物靶点分析,尽量用Swiss-Prot的记录。我曾经在一个项目里用了TrEMBL的数据,结果靶点功能注释全是预测的,最后验证阶段翻车了。嗯,从那以后我每次都会先看Status字段。

UniProt的REST API非常强大。我最常用的两个操作:根据ID检索蛋白功能,以及根据基因名或者疾病名批量映射到UniProt ID。

# 根据UniProt ID获取蛋白注释
import requests

uniprot_id = "P23219"  # COX-1,阿司匹林的靶点
url = f"https://rest.uniprot.org/uniprotkb/{uniprot_id}.json"
response = requests.get(url)
data = response.json()

# 提取基因名和功能描述
gene_name = data["genes"][0]["geneName"]["value"]
function_comment = None
for comment in data["comments"]:
    if comment["commentType"] == "FUNCTION":
        function_comment = comment["texts"][0]["value"]
        break
print(f"Gene: {gene_name}, Function: {function_comment}")
关键点:UniProt的idmapping接口可以把基因名、疾病名、Ensembl ID等批量转为UniProt ID。格式支持选择JSON或TSV。我通常用TSV,因为直接用Pandas读方便。
# 批量映射基因名到UniProt ID
import requests

gene_list = ["PTGS1", "PTGS2", "CYP2C9"]
params = {
    "from": "GENENAME",
    "to": "ACC",
    "format": "tsv",
    "query": " ".join(gene_list)
}
url = "https://rest.uniprot.org/idmapping/run"
response = requests.post(url, data=params)
job_id = response.json()["jobId"]

# 轮询结果
import time
while True:
    status_url = f"https://rest.uniprot.org/idmapping/status/{job_id}"
    status = requests.get(status_url).json()
    if status["jobStatus"] == "FINISHED":
        break
    time.sleep(1)

result_url = f"https://rest.uniprot.org/idmapping/uniprotkb/results/stream/{job_id}?format=tsv"
result = requests.get(result_url)
print(result.text)
注意:UniProt的API有频率限制。免费用户每分钟最多15次请求。批量操作建议使用ID Mapping的异步模式,避免被限流。

CTD:连接化学、基因与疾病

DrugBank和UniProt只能告诉你药物和靶点的关系,但你要研究一种药到底影响哪些疾病通路、有没有毒副作用,就得靠CTD(Comparative Toxicogenomics Database)。CTD的核心资产是化学-基因-疾病三元组关系,而且是人工整理加文本挖掘双保险。我在做一个抗癌药物重定位项目时,就是靠CTD的chemical_disease关系表找到了老药的新适应症。

CTD提供TXT格式的原始数据下载,同时也有REST API。我个人觉得直接下载全套数据最省事,更新频率每月一次,够用。

# 从CTD下载化学-疾病关联文件(直接wget更简单)
# 命令行:curl -O https://ctdbase.org/reports/CTD_chemicals_diseases.tsv.gz
# 用Python读取
import pandas as pd

df = pd.read_csv("CTD_chemicals_diseases.tsv.gz", sep="\t", compression="gzip",
                 usecols=["ChemicalName", "DiseaseName", "DirectEvidence"])
# 筛选出有直接证据的关联
direct = df[df["DirectEvidence"].notna()]
print(direct.head())

CTD的数据量不小,化学-疾病关联有150万+条,基因-疾病关联300万+条。查询时记得加索引。我用DuckDB做本地分析,比Pandas快很多,内存也不炸。

三库联合:构建你的关系抽取基础

实际项目中,我习惯把这三个数据库当作一个管道来处理:

  1. 起点:从DrugBank拿到药物及靶点UniProt ID列表。
  2. 丰富:去UniProt补充靶点的Gene Symbol、家族、功能域信息。
  3. 扩展:用CTD查询这些药物或基因关联的疾病,以及毒性数据。
  4. 关联:将三元组(药物, 靶点, 疾病)整理成结构化数据,作为下游关系抽取的训练/验证集。

下面是我常用的一个数据整合流程示例:

# 伪代码:三库联合构建药物-靶点-疾病关系表
drugs = load_drugbank_targets("drugbank.csv")    # 列:drug_id, uniprot_id
proteins = load_uniprot_info(drugs["uniprot_id"]) # 列:uniprot_id, gene
ctd_links = load_ctd_chemical_disease()           # 列:chemical, disease

# 合并
merged = drugs.merge(proteins, on="uniprot_id")
merged = merged.merge(ctd_links, left_on="drug_name", right_on="chemical", how="left")
merged = merged.dropna(subset=["disease"])
print(merged.shape)
数据库 核心数据 访问方式 更新频率
DrugBank 13,000+药物,5,000+靶点 REST API / CSV下载 每季度
UniProt 2.2亿+蛋白条目(Swiss-Prot 57万) REST API / FTP / SPARQL 每4周
CTD 1,600万+化学-基因-疾病关系 TXT下载 / REST API 每月
个人经验:在做大规模关系抽取时,我从不直接把DrugBank的靶点和CTD的疾病直接做笛卡尔积。那样会产生太多假阳性。更好的做法是用CTD的DirectEvidence标记(如“therapeutic”、“marker/mechanism”)做第一层过滤,准确率能到70%以上。

举个例子,查“阿司匹林”和“结直肠癌”的关联。在CTD里能看到直接证据是“Therapeutic”,说明有临床证据支持。再加上UniProt里COX-1/COX-2抑制机制,就可以形成一个高质量的关系三元组,用来训练你的关系抽取模型。

数据库只是起点,后面的特征表示和模型训练才是重头戏。不过先把地基打牢,后面就不会走偏路。这些库我用了五六年,每次版本更新都会带来惊喜——比如CTD最近加入了疾病-表型关系,DrugBank增加了药物-转运体注释。保持跟踪,你的数据源质量决定了模型的上限。