尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ChEMBL实操指南:靶点查询与活性数据清洗全流程

ChEMBL实操指南:靶点查询与活性数据清洗全流程 做药物设计、化学生物学或者干计算这块的人应该都绕不开ChEMBL这个数据库。不管是查一个靶点有哪些已知的活性化合物还是为了训练模型批量收集IC50数据ChEMBL都是最常用的数据源头之一。但说实话会用这个库和真正用好这个库是两回事——很多人第一次从ChEMBL拉数据要么被它庞大的数据模型绕晕要么被五花八门的单位和活性类型折磨到怀疑人生。这篇文章就围绕“靶点查询”和“活性数据处理”这两件事把ChEMBL从入门到实操的流程完整走一遍适合刚接触生信/化学信息学的同学也适合已经用过但被数据清洗坑过的老手。1. 认识ChEMBL药物研发圈子的活性数据底座1.1 ChEMBL里到底存了什么ChEMBL是由欧洲分子生物学实验室-欧洲生物信息学研究所维护的开源数据库核心使命是把文献里分散的化合物-靶点活性实验数据整理成结构化、可检索、可下载的数据资源。打个比方PubChem更像一个最大的化合物信息库什么结构、物化性质都有而ChEMBL的核心是“活性”——某化合物在某个实验中、对某个靶点、表现出多少抑制或激活活性。这个定位非常精准也非常稀缺。从数据对象来看ChEMBL主要包含五类核心实体化合物分子molecule以规范化后的化学结构存储包含SMILES、InChI、分子量、logP等靶点target主要是蛋白靶点包括人类、鼠、其他物种的各类酶、受体、转运体等实验assay一条实验记录记录了这个实验的背景、方法学binding还是functional、所属文献活性数据activity具体到每个化合物在该assay里的测试结果比如IC5010nM文献与专利每条数据的出处追溯。目前ChEMBL里收录了几百万个化合物、上万个靶点活性数据记录达到千万级别。具体数字随着版本更新一直在涨但这不是重点。重点是这个库里既有上市药物和临床候选分子也有大量化学探针和文献化合物覆盖面足够支撑常见的靶点调研和数据集构建任务。1.2 为什么靶点查询绕不开它做虚拟筛选之前有个问题必须先搞清楚这个靶点有哪些已知活性化合物这些化合物活性的量级是什么水平阳性对照该选什么ChEMBL基本上是回答这类问题的最快路径。你不需要一篇篇翻文献去抄表格直接查靶点就能拿到整理好的活性列表还能关联到对应的文献出处。另一个高频场景是构建机器学习训练集。做ADMET预测、活性分类、分子生成模型都需要标准化的大规模活性数据。这时候ChEMBL的价值就体现出来了——它不仅提供了原始数据还在入库时做了部分标准化比如很多记录直接给出pChEMBL值还有confidence score这样的质量标签辅助筛选。虽然数据处理仍然要自己做但基础的坑它已经帮你填了一部分。2. 靶点查询实操网页端、API接口、Python客户端2.1 网页端查询从基因名或蛋白名入手网页端是最直观的入口。打开ChEMBL官网在顶部搜索框输入EGFR、BRD4这类基因名或者输入蛋白全名基本都能找到对应靶点。搜索结果的命中列表会显示靶点类型、物种、ChEMBL ID一眼就能判断是不是你要找的对象。点进靶点页面之后你会看到这个靶点的详细信息首选名称、别名、物种、UniProt ID、蛋白序列、分类信息等。往下翻还能看到关联的化合物数量、assay数量以及可以直接浏览的活性数据列表。网页端的活性数据表支持筛选和排序比如只看human来源、只看IC50类型、按活性值排序也可以直接导出CSV。第一次熟悉数据时我强烈建议先用网页端浏览一遍目标靶点搞清楚数据长什么样、大概有多少量级再决定下一步怎么写脚本批量处理。2.2 API接口直接拉JSON当你需要程序化获取数据或者要处理大量靶点时网页端就不够用了。ChEMBL提供了RESTful API端点设计得很规整比如查靶点信息GET https://www.ebi.ac.uk/chembl/api/data/target/CHEMBL184.json返回的就是一个包含靶点信息的JSON对象。用Python的requests库可以直接解析。对于不确定名字的靶点可以用搜索端点GET https://www.ebi.ac.uk/chembl/api/data/target/search?qEGFRAPI还支持各种过滤参数比如按物种过滤、按靶点类型过滤。拉活性数据时最常用的端点是GET https://www.ebi.ac.uk/chembl/api/data/activity?target_chembl_idCHEMBL184这里会返回多条活性记录而且会自动做分页。注意默认每页只有20条要控制limit和offset参数比如设置limit1000然后通过多次请求翻页拿全所有数据。API接口的优点是不需要额外装库任何一个能发HTTP请求的语言都能用适合写进自己的数据管道里。2.3 Python一行代码搞定靶点数据如果你用Python做数据处理强烈建议直接用官方维护的chembl_webresource_client库它把API封装得很省心。安装就一行pip install chembl_webresource_client然后用起来也是真的简洁。查靶点from chembl_webresource_client.new_client import new_client targets new_client.target target_info targets.get(CHEMBL184) print(target_info[pref_name]) print(target_info[organism])查某个靶点的活性数据activities new_client.activity res activities.filter(target_chembl_idCHEMBL184).filter(standard_typeIC50) import pandas as pd df pd.DataFrame.from_records(res) print(df.head())这个客户端最大的好处是不用自己处理分页——它会把符合条件的记录自动迭代完相当于一个惰性加载的迭代器。数据量大时它会自动分批拉取并缓存省去很多麻烦。踩过API手写分页的坑之后我基本上全换成这个库了。3. 活性数据的清洗与标准化把原始数据变成可用模型3.1 单位换算先把nM、uM、M统一成摩尔从ChEMBL拉出来的活性数据单位那列非常不统一。虽然标准单位大多是nM但不同文献、不同实验室的实验报告里M、mM、uM、nM甚至pM都可能冒出来。如果不做单位统一后面建模、比较活性的时候会出大问题——一个10nM和一个10uM的IC50差了1000倍直接混在一起算显然是不对的。处理的第一步是把所有浓度单位统一换算成摩尔浓度单位换算成摩尔MMvalue × 1mMvalue × 1e-3uMvalue × 1e-6nMvalue × 1e-9pMvalue × 1e-12代码上可以这么处理import numpy as np def convert_to_molar(row): unit row[standard_units] value row[standard_value] if unit M: return float(value) elif unit mM: return float(value) * 1e-3 elif unit uM: return float(value) * 1e-6 elif unit nM: return float(value) * 1e-9 elif unit pM: return float(value) * 1e-12 else: return np.nan df[value_molar] df.apply(convert_to_molar, axis1)有的记录连单位都没有这些记录建议直接标记为缺失或剔除因为没法确定数值的量纲硬猜风险太大。3.2 从IC50到pChEMBL一个关键对数变换浓度值跨了几个数量级之后很适合用负对数来表征。pChEMBL的定义是pChEMBL -log10(molar_IC50)这样把0.1nM到100uM的浓度范围压缩成了10到4左右的连续数值数值越大活性越强解释起来非常直观。你可以把它理解成pH——pH是氢离子浓度的负对数pChEMBL就是活性浓度的负对数。举个例子一个化合物对EGFR的IC50是10nM换算成摩尔是1e-8MpIC50就是8。另一个化合物IC50是1uMpIC50只有6。两者在图上画出来数值差异就很清楚了。ChEMBL里很多记录本身自带pchembl_value字段但注意它不一定每行都有值。如果原始记录缺少单位、值不完整或者活性类型不是浓度型比如%inhibitionpchembl_value就会空缺。最稳妥的做法是自己从standard_value和standard_units算一遍确保逻辑统一df[pChEMBL] -np.log10(df[value_molar])计算完之后可以顺手画个分布直方图看看整体活性分布是否合理是否存在明显的离群值这一步虽然简单但很管用。3.3 数据筛选、去重与质量评估清洗活性数据时至少还要过三关。第一关是relation字段。ChEMBL的活性数据里relation通常有、、三种。表示确定的值和表示限定边界比如IC50 10000 nM意思是很弱测不到精确值。建模型时如果对精度要求高建议只保留的记录如果只是做分类或者趋势分析可以把、单独标记不要直接混在连续值里算。第二关是confidence score。这个分数代表靶点归属的可靠程度。高置信度比如9一般表示靶点蛋白的映射有明确证据低置信度可能是通过同源性推断的数据参考时要多留个心眼。常规做法是优先保留高置信度记录或者至少做一次敏感性分析看看筛选前后结论会不会变。第三关是同一化合物的多条记录。同一个化合物对同一个靶点很可能在多个assay里被测试得到不同的IC50。这时候需要决定怎么聚合取最小值最乐观估计、取中位数稳健估计、还是保留质量最高的那条记录。我的习惯是先看看数据量的分布如果重复记录很多一般取中位数能削弱极值影响如果数据量少就全保留并在下游建模时加入证据权重。4. 从EGFR到活性化合物端到端实操记录4.1 确定靶点对象下面用一个具体例子把整个流程串起来。选择EGFR表皮生长因子受体因为它数据量大、类型丰富非常适合用来演示。在ChEMBL里人类EGFR的靶点ID是CHEMBL184物种是Homo sapiens。这一步一定不要想当然多确认一遍物种和ID否则后面拉到小鼠、大鼠的数据或者拉到别的异构体就白忙活了。先通过客户端确认一下目标targets new_client.target t targets.get(CHEMBL184) print(t[pref_name], t[organism], t[target_type])4.2 拉取全部IC50数据第二步是拉取EGFR的所有IC50活性数据。注意这里过滤了standard_type为IC50避免把Ki、EC50等其他类型混进来。当然你也可以同时拉多种类型但处理时一定要分开或者打上类型标签activities new_client.activity res activities.filter(target_chembl_idCHEMBL184).filter(standard_typeIC50) df pd.DataFrame.from_records(res) print(df.shape) print(df[[molecule_chembl_id, standard_value, standard_units, pchembl_value]].head())拉完之后看一眼行数、列名、缺失情况。通常这个数据集有几千条包含化合物ID、活性值、单位、assay信息、文献来源等。注意有些列是嵌套的JSON对象比如target_organism、document等取值时要稍微处理一下。这时候不要急着往下走先做一个简单的数据概况统计print(df[standard_units].value_counts()) print(df[relation].value_counts())确认单位和relation分布做到心里有数。4.3 结构标准化与分子描述符活性数据里都有molecule_chembl_id但下游建模往往需要化合物的结构信息。所以下一步是把化合物结构跟活性数据关联起来。一种做法是遍历每个molecule_chembl_id从ChEMBL拉取SMILESmolecules new_client.molecule chembl_ids df[molecule_chembl_id].unique() smiles_dict {} for chembl_id in chembl_ids: mol molecules.get(chembl_id) smiles_dict[chembl_id] mol[molecule_structures].get(canonical_smiles)考虑到可能有几千个化合物全部拉取会有一点耗时。如果网络稳定这个方法是可行的如果量大建议直接下载ChEMBL全库的SDF或者CSV文件在本地join效率高很多。有了SMILES之后可以用RDKit对结构做标准化去除盐基保留母体分子中和电荷、规范化互变异构可选取决于建模需求生成Morgan指纹或者计算分子描述符。到了这一步你已经拿到一份“活性值化合物结构”的完整数据集可以用来做SAR分析、训练分类模型、或者构建虚拟筛选的活性正样本集合。整个流程从靶点查询到数据处理算是真正闭环了。5. 常见问题与排查技巧实录5.1 靶点查不到或ID对不上这是被问得最多的问题。搜索一个基因名时有时候返回结果一大堆但就是找不到你要的那个“公认”靶点。原因往往是命名混乱同一个蛋白在不同文献里可能叫EGFR、ErbB1、HER1不同数据库系统之间叫法差异更大。排查思路是先确认UniProt ID。ChEMBL的靶点页面都有关联的UniProt ID这是跨数据库对齐的金标准。你可以在UniProt上搜基因名拿到标准accession号再回ChEMBL里搜索这个accession号就能准确定位到靶点。另一种情况是物种不对比如你要的是人类CDK2搜索结果里可能混着非洲爪蟾的CDK2这时候就看organism字段按物种过滤掉。还有一个坑是同名蛋白的多构型。比如多个靶点记录对应同一个基因的不同剪接体或突变体它们的ChEMBL ID是不同的。如果拿到的数据集活性分布有明显分层怀疑是不是包含了对突变体的数据检查一下target_id和target_organism有没有混入。5.2 活性类型和量纲的特殊情况ChEMBL里的standard_type远不止IC50常见的还有EC50、Ki、Kd、Potency甚至%inhibition。IC50是半抑制浓度EC50是半最大效应浓度Ki和Kd是结合亲和力指标它们的物理意义和数值量纲都有区别原则上不能直接混在一起做回归。如果确实需要合并建议加一个type标签并考虑做类型到统一指标的映射对于Ki和Kd某些场景下可以近似等价但要说明假设。%inhibition这种数据要特别小心。它是单浓度下的相对抑制率没有浓度梯度就不能从%inhibition推算出IC50。有些新手拿到数据后把%inhibition当成浓度值直接算pChEMBL结果肯定错得离谱。处理这类记录的正确方式是单独存放、单独分析。另外要注意缺失值。有的记录standard_value为空但pchembl_value有值有的则反过来。清洗时最好自己算一遍浓度和pChEMBL不要完全依赖字段是否为空来判断。5.3 API请求失败与限流处理用Python客户端拉大批量数据时有时会遇到请求失败或者返回503/429错误。这通常是请求频率太高被服务端限流了。解决办法很简单降低请求频率、加延时、失败重试。代码上可以加个简单的重试机制import time import random def fetch_with_retry(func, retries3, delay1.0): for i in range(retries): try: return func() except Exception as e: print(fRequest failed: {e}, retry {i1}/{retries}) time.sleep(delay random.uniform(0, 0.5)) raise RuntimeError(Max retries exceeded)另外一个实用建议是如果数据量达到几万甚至几十万就别一个一个小请求去拉数据了。ChEMBL官网提供全库数据下载包括MySQL导出文件、SDF文件、CSV文件直接下载到本地再查询过滤速度远超在线API也不占用服务端资源。做本地数据库同步时可以考虑用官方提供的dump文件而不是在线API暴力拉取。5.4 活性和文献溯源别忘了记录出处很多时候我们只关心活性值忽略了文献出处等到写文章或者汇报时才发现每条数据都要能追溯来源。ChEMBL的记录里都带有document字段包含PubMed ID和文献标题。清洗的时候建议把这条信息保留下来至少留一个doc_id或者journal信息后面整理数据补充材料时能省一大半时间。有些数据是来自专利的这部分通常不会出现在常规文献数据库里引用规范也不太一样使用时要注意合规和引用的格式要求。5.5 数据版本不一致结果复现的关键变量ChEMBL每隔一段时间会发布新版本靶点ID、化合物记录、活性数据都可能发生变化。同一个查询语句在新旧版本里得到的结果行数和数值可能有细微差别。如果团队协作或者写论文一定要在数据准备流程里记录ChEMBL版本号。客户端库也有版本属性下载全库dump时文件名里通常也有日期把这些信息保留下来才是真正的可复现。我个人的习惯是把数据处理脚本、版本号、筛选规则一起放在项目目录下甚至把关键的中间结果导出成CSV存档。虽然看起来多了一步但遇到需要回溯数据来源的场景这些记录就是救命稻草。在ChEMBL上跑通一条从靶点到活性的数据流其实并不复杂难点主要在于细节单位、类型、版本、质量筛选、去重策略每一个环节都会影响最终数据集的质量。我自己做过很多次这类数据处理之后最深的体会是永远不要相信原始字段会“自动正确”每个字段都要亲眼确认一遍逻辑再进入下游流程。你现在如果正在搭建自己的活性数据管道建议第一次先挑一个数据量适中的靶点把整条链路跑通、画出活性分布、沉淀成脚本后面再复制到其他靶点就会顺手得多。
返回列表