信息速览
INFOBOX
| 项 | 值 |
|---|---|
| 全名 | CPIC(Clinical Pharmacogenetics Implementation Consortium,临床药物基因组学实施联盟) |
| 维护方 | CPIC,现并入 ClinPGx(PharmGKB + CPIC + PharmCAT 三家合一) |
| 基因数 | 132 |
| 药物数 | 324 |
| 指南数 | 29 |
| 药-基因对 | 635 |
| 等位基因 | 1,378 |
| 用药推荐 | 2,115 条 |
| 双倍型映射 | 112,820 条 |
| 支撑文献 | 1,155 篇 |
| 接口 | api.cpicpgx.org/v1,无需注册,全表 JSON |
| 许可 | CC0 / 公有领域(CPIC 自称 Creative Commons public domain) |
| 最大的坑 | 它不是「药-基因关联库」,是「药-基因-剂量建议库」——636 对里只有 136 对真的给了推荐 |
§0 E-E-A-T 信任声明与免责声明
我们是谁:千方病案医学编辑部,为中文医学 AI 社区整理可训练数据集的结构化说明。
本条目怎么来的:全部数字来自 2026-10-23 对 api.cpicpgx.org/v1 各端点的实测。七个主表的行数用 HEAD 请求 + Prefer: count=exact + Range: 0-0 读 Content-Range 头取得(这是 PostgREST 的标准计数方式,不需要拉全表)。分布统计取自实际返回的 JSON:pair 635 条全量、allele 1,378 条全量、recommendation 2,115 条全量、population 3,917 条全量、drug 324 条全量。diplotype 112,820 条体量过大无法一次性拉取,改为按 132 个基因逐个拉取(实测返回 30,611 行,受各端点 limit 上限约束,见 §7.2)。
我们不做什么:本条目不评价任何一条推荐在临床上的正确性,不判断证据分级是否合理,不做 benchmark。CPIC 说什么就是什么——它是这个领域公认的实施标准,我们只负责把它介绍清楚。
重要提示:本条目不是医疗建议。任何用药决策必须由有执照的临床医师或临床药师结合患者具体情况作出。CPIC 的推荐是「群体层面的规则」,不针对个体,且明确不覆盖药物相互作用、肝肾功能、年龄体重等非遗传因素。
已知局限:
diplotype表未取全(30,611 / 112,820,约 27.1%),所有涉及双倍型的比例都标注了「抽样」。cpicpgx.org已于 2025-07-30 起重定向到clinpgx.org/cpic,但api.cpicpgx.org仍在服务。我们实测两个域名的 API 不同:api.clinpgx.org/v1/gene返回 404(路径变了),api.cpicpgx.org/v1/gene返回 200。本篇所有数据来自仍在服务的旧域名。 这个域名能活多久,我们无法保证。- 我们没有核对 ClinPGx 侧的对应表是否与 CPIC 侧逐行一致。
§1 数据集概览
§1.0 📌 30 秒速览
CPIC 做的事情,一句话能说完:它把「你带这个基因型,用这个药会怎样」写成一条条可执行的建议,并且给每条建议标上强度。
规模(2026-10-23 API 实测):
| 表 | 行数 | 一句话 |
|---|---|---|
gene |
132 | 收录的基因 |
drug |
324 | 收录的药物 |
guideline |
29 | 已发布的指南 |
pair |
635 | 药-基因对(注意不是 132 × 324) |
allele |
1,378 | 等位基因(星号等位) |
recommendation |
2,115 | 用药推荐正文 |
diplotype |
112,820 | 双倍型 → 表型映射 |
test_alert |
2,213 | 检验后警示文本(可直接塞进 EHR) |
publication |
1,155 | 支撑文献 |
population |
3,917 | 人群等位基因频率的样本描述 |
allele_frequency |
387,734 | 逐人群的等位基因频率 |
一句话判读:表很小,但是成品。 112,820 条双倍型映射放在基因组学里是极小的量,但它是从「基因型」到「表型」再到「剂量」的完整链路——这个链路在别处没有。
最容易搞错的一点:CPIC 不是「药-基因关联数据库」。635 个药-基因对里,只有 136 对(21.4%)被标记为「用于推荐」(
usedforrecommendation = true),只有 96 对拿到最高的 A 级。剩下的 500 对是「有关联但还不足以改处方」。把它当关联库用,会把「有研究」和「该调整」混为一谈。
§1.1 技术摘要
| 维度 | 内容 |
|---|---|
| 数据形态 | 关系型数据库的 REST 暴露,PostgREST 风格(支持 select / eq. / limit / Prefer: count=exact) |
| 核心表 | recommendation(推荐)、diplotype(双倍型)、allele(等位基因)、pair(药-基因对) |
| 连接键 | 基因名(CYP2D6)、药物 ID(RxNorm:38400)、指南 ID(104243)、等位基因名(*4) |
| 更新节奏 | 随指南更新,逐条发布,无固定全库版本号 |
| 增量识别 | change_log 表 907 条,记录每次改动 |
| 访问门槛 | 零——不需要 token、不需要注册、不限 IP(但大规模使用官方建议先联系) |
| 单条记录体积 | gene 约 600 B;recommendation 约 1-2 KB;diplotype 约 700 B |
为什么它值得单独收录:药物基因组学领域有大量「某某基因与某某药相关」的证据,但能落到处方上的只有一小层。CPIC 就是这一层的官方定义。它对 AI 的价值不是「多一个数据集」,而是它给出的是答案而不是线索——recommendation 表里每一行都是一句完整的、可以直接当标签用的句子。
§1.2 战略价值
第一条价值:它是「多基因联合决策」的少数真实样本。
一条 test_alert 记录(实测,id = 8481816):
drugid: RxNorm:704(阿米替林)
genes: ["CYP2D6", "CYP2C19"]
lookupkey: {CYP2D6: "0.0", CYP2C19: "No Result"}
alerttext: "CYP2D6 and CYP2C19 genetic status may be predictive of ... altered
drug metabolism. This patient is predicted to be a CYP2D6 poor metabolizer ...
consider a 50% reduction of recommended starting dose ... A CYP2C19 genotype
does not appear to have been ordered for this patient ..."
这一段文本里同时包含:两个基因的条件、其中一个「未检测」的处理、定量建议(减 50%)、以及缺失基因型的兜底逻辑。这是真实临床决策支持的完整形态,而绝大多数「药物基因组学数据集」只给单基因单药的单点关联。
第二条价值:它是「证据分级」这件事的教科书样本。 四级 A/B/C/D 加上推荐强度 Strong/Moderate/Optional,构成了一个双层分级体系——证据强度和推荐强度不是一回事。这个双层结构本身值得学习:它承认「证据很强但没有更好选择,所以还是推荐用原药」。
第三条价值:它把「表型」这个词标准化了。 药物基因组学最难的一步不是测基因型,是把基因型说成临床能用的表型(poor / intermediate / normal / rapid metabolizer)。CPIC 的 diplotype 表把 112,820 种双倍型组合全部映射到这几档,这是行业事实标准,PharmCAT、各类 EHR 药物基因组学模块都按它实现。
§1.3 同类资源横向对比
| 资源 | 覆盖 | 是否给剂量建议 | 证据门槛 | 适合 |
|---|---|---|---|---|
| CPIC | 132 基因 / 324 药 | 是,且分级 | 只收已定级、可实施的 | 处方决策、CDS 标签 |
| PharmGKB / ClinPGx 全库 | 远大于 CPIC | 部分 | 收录未分级证据 | 文献挖掘、机制研究 |
| DPWG(荷兰) | 与 CPIC 部分重叠 | 是 | 独立分级,常与 CPIC 不一致 | 欧洲场景、交叉验证 |
| FDA 药物标签 | 按药 | 部分有 PGx 段落 | 监管口径 | 合规场景 |
| PharmVar | 星号等位基因定义 | 否 | 只做等位基因命名 | 基因型判定 |
关键区别在第二列:CPIC 与 PharmGKB 是**「成品 vs 原料」**关系。PharmGKB 收集所有证据(包括互相矛盾的、样本量很小的),CPIC 只保留能写成处方句子的那一层。做模型训练两者都要,但标签来源必须是 CPIC——拿 PharmGKB 的未分级证据当标签,等于把噪声当真值。
CPIC 与 DPWG 的不一致是真实存在的,且不该被抹平。 同一对药-基因,荷兰 DPWG 与 CPIC 的推荐有时方向相同、剂量不同,有时结论相反。这不是谁错,是两套独立的证据评估流程。 做跨体系数据集时,这个分歧本身是有价值的标签(「存在争议」),而不是需要清洗的脏数据。
§1.4 版本时间轴
CPIC 没有全库版本号,它是逐条更新的。可用的时间信号有三个:
| 信号 | 字段 | 说明 |
|---|---|---|
| 记录级版本 | version |
每条记录(gene / recommendation / pair / diplotype)自带版本号,从 1 递增 |
| 变更日志 | change_log 表 907 条 |
每次改动一行,可据此做增量同步 |
| 指南发布日 | guideline.url 指向 ClinPGx 页面 |
页面里有正式发表信息与 PMID |
version 字段的实测差别很大:
gene.F5的version = 3pair(CYP2D6 × 可待因)的version = 88recommendation(阿巴卡韦 × HLA-B)的version = 1
这说明「版本号」是记录级的编辑次数,不是数据发布日期。 一个药-基因对改了 88 次(因为指南反复修订),一个基因只改过 3 次(因为基因本身的注释很稳定)。不能用它排序新旧。
想钉住版本,唯一可靠的办法是给每张表算一个内容哈希(按主键排序后对全表 JSON 做 SHA256)。CPIC 不给快照,只有自己存快照。这一点与 RNAcentral、Rfam 那种「发布 15.1、有固定 FTP 目录」的模式完全不同——CPIC 是「活库」,不是「发行版」。
§1.5 典型应用场景
| 场景 | 用哪些表 | 产出 |
|---|---|---|
| 药物基因组学问答模型 | recommendation + guideline |
「CYP2D6 慢代谢者用可待因怎么办」→ 训练问答对 |
| EHR 检验后警示 | test_alert |
2,213 条现成警示文本,可直接嵌入 CDS |
| 基因型 → 表型归一化 | diplotype + allele |
112,820 条映射,训练序列到表型的分类器 |
| 人群频率先验 | allele_frequency + population |
387,734 条频率,做「这个人群该不该常规检测」 |
| 指南摘要生成 | guideline 29 部 |
长文摘要任务 |
| 证据强度判别 | recommendation.classification |
分类任务:这条建议是 Strong 还是 Optional |
最实用的一个是第二行。test_alert 表 2,213 条记录是已经为 EHR 写好的自然语言警示,带 cdscontext(Pre-test / Post-test)区分检测前后。这批文本不是从论文里摘的,是专门为「直接显示给医生看」写的,措辞和结构都经过临床可用性打磨。做中文 EHR 提示语生成时,这是最好的参照样本。
§2 药物基因组学的科学前提
§2.1 从基因型到剂量的四步链
CPIC 的全部数据结构,本质是把一条四步链拆成四张表:
基因型(diplotype)→ 表型(phenotype)→ 临床含义(implications)→ 建议(recommendation)
diplotype 表 generesult 字段 implications 字段 drugrecommendation
| 步骤 | 例子(CYP2D6 × 可待因) | 落在哪个字段 |
|---|---|---|
| 1. 基因型 | *4/*4(两个无功能等位) |
diplotype.diplotype |
| 2. 表型 | Poor Metabolizer | diplotype.generesult |
| 3. 临床含义 | 可待因无法转化为吗啡,镇痛无效 | recommendation.implications |
| 4. 建议 | 避免使用可待因,改用吗啡或非阿片类 | recommendation.drugrecommendation |
这个拆分方式很值得学。它把「生物学推断」和「临床决策」分开:diplotype 表只管前两步(纯遗传学),recommendation 表管后两步(临床)。所以同一套双倍型映射可以被多个不同的临床推荐体系复用(CPIC 一套、DPWG 一套),因为前两步是共通的。
这也是一个天然的切分点:如果你的任务是「从测序数据判基因型」,只用
allele+diplotype,完全不涉及临床判断,没有伦理风险;只有当任务跨到recommendation那一步,才开始有「建议是否适用于这个患者」的责任问题。
§2.2 星号等位基因与双倍型
药物基因组学里的「基因型」不是 A/T/C/G 四选一,是星号命名法(star allele nomenclature):
| 记号 | 含义 | 例 |
|---|---|---|
*1 |
参考等位(正常功能) | CYP2D6*1 |
*4 |
一个具体变异,功能缺陷 | CYP2D6*4(剪接位点变异,无功能) |
*5 |
整个基因缺失 | CYP2D6*5 |
*2xN |
基因重复,N 份拷贝 | CYP2D6*2x2(两份拷贝,超快代谢) |
*10 |
亚洲人群常见的减功能等位 | CYP2D6*10 |
人体是二倍体,所以基因型是两个星号拼起来:*1/*4(一个正常一个缺陷)、*4/*4(都缺陷)、*1/*1(都正常)。这个组合就叫 diplotype(双倍型)。
为什么 *5 和 *2xN 特别重要:它们是拷贝数变异,不只是序列差异。*5/*5(两个等位都缺失)意味着这个人完全没有这个基因;*2x2/*2x2 意味着有四份功能拷贝。这两种极端在剂量上必须单独处理,而普通的「变异位点表」根本表达不了——这就是 CPIC 必须用双倍型而不能只用 SNP 的原因。
allele 表的 1,378 条是怎么分布的:
| 基因 | 等位数 | 说明 |
|---|---|---|
| RYR1 | 347 | 恶性高热相关,变异极多且分散 |
| CYP2D6 | 208 | 研究最透的代谢酶 |
| G6PD | 187 | 葡萄糖-6-磷酸脱氢酶缺乏症 |
| CFTR | 104 | 囊性纤维化,且带药物响应标签 |
| CYP2C9 | 94 | 华法林、苯妥英 |
| DPYD | 84 | 氟尿嘧啶类毒性 |
| NAT2 | 59 | 异烟肼 |
| CYP2B6 / CYP2C19 / TPMT | 各 49 |
只有 22 个基因有等位基因级定义,而收录了 132 个基因——这是本篇最重要的结构事实之一。110 个基因(83.3%)在 CPIC 里只有药-基因对层面的信息,没有细化到等位基因。 见 §4.2。
§2.3 功能状态:CPIC 的第一个自由文本陷阱
allele 表的 clinicalfunctionalstatus 字段,语义上应该只有五档(正常 / 减功能 / 无功能 / 功能增加 / 功能不确定),实际上有 18 种不同写法:
clinicalfunctionalstatus |
条数 | 占比 |
|---|---|---|
| Uncertain function | 384 | 27.9% |
| No function | 165 | 12.0% |
| Normal function | 130 | 9.4% |
| Decreased function | 124 | 9.0% |
ivacaftor responsive |
103 | 7.5% |
| (空值) | 100 | 7.3% |
Malignant Hyperthermia associated |
98 | 7.1% |
I/Deficient with CNSHA |
86 | 6.2% |
II/Deficient |
53 | 3.8% |
| Unknown function | 52 | 3.8% |
III/Deficient |
37 | 2.7% |
uncertain risk of aminoglycoside-induced hearing loss |
20 | 1.5% |
| Increased function | 15 | 1.1% |
IV/Normal |
5 | 0.4% |
| 其余 5 种杂项 | 各 1-3 | <0.5% |
这张表里藏着四个坑,每一个都会让自动处理出错:
坑一:Uncertain function 与 Unknown function 是两回事,但很容易被当成同义词。 前者是「功能有数据但不足以定档」(如体外实验矛盾),后者是「完全没有功能数据」。合并成一个类别会丢掉一个真实区分。
坑二:ivacaftor responsive 根本不是功能状态。 它是 CFTR 特有的药物响应标签,塞进了功能状态字段。CFTR 的 104 个等位这里,有 103 个是这种写法——意味着 CFTR 在 clinicalfunctionalstatus 字段上几乎不提供常规意义的功能分级。做跨基因聚合时必须把它单独拎出来。
坑三:G6PD 用的是 WHO 酶缺乏分级(I/Deficient with CNSHA、II/Deficient、III/Deficient、IV/Normal),不是常规五档。 这是历史遗留——G6PD 的临床分级体系比药物基因组学早几十年,CPIC 沿用了它。同一个字段,在 CYP 系基因上是一套语义,在 G6PD 上是另一套。
坑四:Increased function 只有 15 条(1.1%)。 这与直觉相反——「超快代谢」是药物基因组学里非常著名的现象(CYP2D6 超快代谢者用可待因会中毒),但在等位基因级只有 15 条记录。原因是超快代谢大多由拷贝数增加(*2xN)导致,而不是单个等位基因的功能增强。拷贝数变异在 allele 表里表现为「同一等位的多拷贝标记」,功能状态本身仍写 Normal function。
实操结论:
clinicalfunctionalstatus不能用枚举值对待。正确处理是先按基因分组,再在组内映射到统一五档(CYP 系一套规则、G6PD 一套、CFTR 单独一套),不要做全局字符串映射。§6.1 给了代码。
§2.4 证据分级与推荐强度:两套独立的尺子
CPIC 有两套分级,它们不是一回事:
第一套:药-基因对的 CPIC 证据等级(pair.cpiclevel)
| 级别 | 含义 | 条数 | 占比 |
|---|---|---|---|
| A | 证据充分,应据此改变处方 | 96 | 15.1% |
| B | 证据较强,可以考虑改变处方 | 36 | 5.7% |
| B/C | 介于 B 与 C 之间 | 56 | 8.8% |
| C | 证据不足或只在特定情况下适用 | 284 | 44.7% |
| C/D | 介于 C 与 D 之间 | 15 | 2.4% |
| D | 证据弱,仅作信息 | 134 | 21.1% |
近半数(44.7%)的药-基因对是 C 级。这个数字很关键:它说明「CPIC 收录了」不等于「CPIC 认为该用」。C 级对的典型说明是「有证据,但目前不建议常规检测」。
第二套:推荐的临床强度(recommendation.classification)
| 强度 | 含义 | 条数 | 占比 |
|---|---|---|---|
| Strong | 应执行,获益明确 | 591 | 27.9% |
| Moderate | 可执行,获益较明确 | 357 | 16.9% |
| Optional | 可选,获益不确定 | 1,047 | 49.5% |
| No Recommendation | 不推荐任何调整 | 108 | 5.1% |
n/a |
无分级 | 12 | 0.6% |
两套尺子的关系值得单独说清楚:
cpiclevel判的是「这对药-基因有没有足够证据支持做检测」,classification判的是「知道了基因型之后要不要改处方」。 前者是「该不该测」,后者是「测了怎么办」。
所以会出现这种组合:一个 C 级的药-基因对,对某个特定基因型给出 Strong 推荐。因为 C 级指的是「不必要对所有人大规模检测」,但如果病人已经测了、结果是某个明确的高风险基因型,那就必须改——这时推荐就是 Strong。这两个判断不矛盾,是不同层面的问题。
另一个反直觉的数字:Optional 占 49.5%,几乎一半。这意味着 CPIC 的推荐里,一半是「你自己看着办」。这不代表库没用,恰恰说明它诚实——它没有把「证据不足」包装成「建议这样做」。
§2.5 为什么要收一个「药-基因-剂量」库
库内已有一批基因组学资源(TCGA、GTEx、1000 Genomes 等),但没有一个是「临床决策层」的。它们的共同形态是「变异 → 关联」,终点是 p 值或效应量。
CPIC 的形态是「变异 → 做什么」,终点是祈使句。这个差别对 AI 训练很关键:
| 数据类型 | 典型样本形态 | 训练什么 |
|---|---|---|
| GWAS / 关联库 | (rs123, trait, p=3e-9, OR=1.2) |
关联发现、效应量估计 |
| CPIC | (CYP2D6 *4/*4, 可待因, "避免使用,改用吗啡或非阿片类") |
指令遵循、决策规则、安全边界 |
第二类样本在中文语料里极度稀缺。中文互联网上关于「CYP2D6 慢代谢者能不能用可待因」的内容,多数是科普文章,没有权威的、可溯源的、逐条对应的答案表。CPIC 的 2,115 条推荐 + 2,213 条警示文本,是目前唯一能撑起这类任务的公开来源。
它也和库内的电子健康记录类资源形成互补:EHR 数据回答「实际怎么治的」,CPIC 回答「应该怎么治」。前者是行为,后者是规范。做临床决策模型,两者缺一不可——只有行为数据会学到「大家都这么干」(包括错误做法),只有规范数据会脱离真实场景。
§2.6 CPIC 保证什么、不保证什么
| 保证 | 不保证 |
|---|---|
| 推荐经过同行评议并发表 | 推荐适用于你的患者个体 |
| 证据强度有明确分级 | 分级没有争议(DPWG 常不同意) |
| 双倍型到表型的映射是行业标准 | 所有实验室的检测都能区分这些等位 |
| 每条推荐可溯源到文献 | 文献覆盖了所有人群(主要是欧洲裔) |
| 覆盖主流药物基因组学基因 | 覆盖所有有 PGx 证据的基因 |
最需要注意的一条是最后一行的人种偏倚。population 表 3,917 条样本描述里,族裔分布如下:
| 族裔 | 条数 | 占比 |
|---|---|---|
| European | 1,160 | 29.6% |
| East Asian | 925 | 23.6% |
| Central/South Asian | 406 | 10.4% |
| Latino | 400 | 10.2% |
| Near Eastern | 334 | 8.5% |
| Sub-Saharan African | 329 | 8.4% |
| African American/Afro-Caribbean | 171 | 4.4% |
| American(美洲原住民) | 128 | 3.3% |
| Oceanian | 64 | 1.6% |
东亚裔占 23.6%,这一比例显著高于多数基因组学资源——这对中文用户是好消息。原因很具体:CYP2D6 *10、CYP2C19 *2/*3、ALDH2 *2 这些东亚人群高频等位必须有人群频率数据才能给出有意义的先验,CPIC 为此专门收录了大量东亚样本。
但注意「条数」不等于「人数」。3,917 条是样本描述记录数(每个基因×每个族群×每个来源算一条),不是受试者总数。真实的受试者规模要看
subjectcount字段,单条常是几十到几千人。用 3,917 去估「CPIC 有多少人的数据」是错的,见 §7.7。
§3 数据规格与通道抉择
§3.0 三条通道
| 通道 | 地址 | 适合 | 限制 |
|---|---|---|---|
| REST API(推荐) | https://api.cpicpgx.org/v1/<table> |
首选:全表 JSON,无需注册 | 单次返回有条数上限,大表要分页 |
| Swagger UI | https://api.cpicpgx.org/ |
探索字段、试查询 | 纯前端,需浏览器 |
| ClinPGx 网站 | https://www.clinpgx.org/cpic |
人读、看流程图 | 需 JS 渲染,机器不友好 |
一个必须先搞清的事实:
cpicpgx.org已经不再是独立站点。我们实测https://cpicpgx.org/guidelines/返回 302,跳转到https://www.clinpgx.org/cpic/guidelines。官网首页的最终 URL 也是clinpgx.org/cpic。但 API 域名api.cpicpgx.org仍在正常服务,而api.clinpgx.org/v1/gene返回 404(ClinPGx 的 API 路径不同,是/v1/gene→ 不存在,实际用/v1/chemical、/v1/guidelineAnnotation等)。
这意味着什么:如果你在 2026 年之后写代码,文档里抄来的 api.cpicpgx.org 能用,但它是「旧域名延续服务」;官方新方向是 ClinPGx 的 API,但那套 API 的表结构、字段名、路径都不同。两套并存期间,用哪套必须写明。 本篇用的是仍在服务的 CPIC 那一套。
§3.1 表地图:34 个端点
api.cpicpgx.org/v1/ 的 OpenAPI 规范(swagger 2.0)列出 34 个端点(另有 4 个 rpc/ 存储过程)。核心的 12 个:
| 端点 | 行数 | 一句话 |
|---|---|---|
gene |
132 | 基因:HGNC、Entrez、Ensembl、ClinPGx 四套 ID |
drug |
324 | 药物:RxNorm、DrugBank、ATC、UMLS 四套 ID |
guideline |
29 | 指南:名称、链接、涉及基因 |
pair |
635 | 药-基因对:证据等级、是否用于推荐 |
allele |
1,378 | 等位基因:功能状态、活性值 |
allele_definition |
1,354 | 等位基因的变异位点定义(哪些 SNP 组合成这个星号) |
diplotype |
112,820 | 双倍型 → 表型 |
recommendation |
2,115 | 推荐正文 |
test_alert |
2,213 | 检验后警示文本(可直接给 EHR) |
publication |
1,155 | 支撑文献(PMID) |
population |
3,917 | 人群样本描述 |
allele_frequency |
387,734 | 逐人群等位基因频率 |
几个容易被忽略但很有用的端点:
| 端点 | 用途 |
|---|---|
change_log(907 条) |
增量同步:上次拉取后改了什么 |
gene_result(101 条) |
表型的标准名称字典(PM/IM/NM/RM 等) |
guideline_summary_view / pair_view / recommendation_view |
预连接好的视图,省掉自己 join |
population_frequency_view |
频率与人群描述已连接 |
*_view端点是这个 API 最贴心的设计。recommendation_view已经把recommendation+guideline+drug连好,你不需要知道外键关系就能直接拿到「药物名 + 指南名 + 推荐正文」。新手应该从 view 端点入手,而不是从裸表入手。
§3.2 下载预算
| 目标 | 体积 | 时间 |
|---|---|---|
| 只要推荐表 | recommendation 2,115 条,约 3 MB |
秒级 |
| 推荐 + 指南 + 药物(用 view) | 约 5 MB | 秒级 |
| 等位基因 + 功能状态 | allele 1,378 条,约 1 MB |
秒级 |
| 双倍型全量 | 112,820 条,约 80-100 MB | 实测全量一次性拉取超 7 分钟未完成,需分页 |
| 频率表 | allele_frequency 387,734 条,约 100 MB+ |
分页 |
实测教训:我们尝试一次拉 112,820 条双倍型(?select=...&limit=120000),7 分钟没有返回,只能中止。改为按 132 个基因逐个拉(?genesymbol=eq.CYP2D6&limit=5000),3 分 46 秒拿完 131 个基因、30,611 行。
结论:CPIC 的大表必须按维度切分拉取,不要试图一次拿全表。 按基因切是最自然的分法(
diplotype只有 18 个基因有数据),按guidelineid切也可以。分页参数limit有上限(实测limit=120000会被服务端接受但实际长时间不返回,应按 5,000 一批)。
§3.3 更新与版本机制
| 机制 | 有无 | 说明 |
|---|---|---|
| 全库版本号 | 无 | 没有「CPIC v3.1」这种概念 |
| 快照下载 | 无 | 不提供时间点快照 |
| 记录级版本 | 有 | 每表有 version 字段 |
| 变更日志 | 有 | change_log 907 条 |
| 数据库迁移历史 | 有 | flyway_schema_history 端点(表结构版本,不是数据版本) |
这是 CPIC 与「发行版型」数据库(Rfam、RNAcentral、Ensembl)最大的结构差异:它是活库,随时变,且不可回溯。
所以正确的版本管理姿势是:
- 每次拉取都存原始 JSON 快照(带时间戳),不要只存处理后的结果。
- 对每张表算内容哈希:按主键排序 → 序列化 → SHA256。
- 用
change_log做增量,但每月至少做一次全量重拉对账——因为change_log只记录「改了什么」,如果某次改动被回滚或漏记,增量会累积偏差。
flyway_schema_history的存在说明后端是 PostgreSQL + Flyway 迁移,这也解释了为什么 API 是 PostgREST 风格(eq.、select、Prefer: count=exact全是 PostgREST 的特性)。知道这一点很实用:PostgREST 的所有查询语法在这里都适用,包括order、offset、limit、not.is.null、嵌套 select。
§3.4 技术栈与溯源链
| 环节 | 实现 |
|---|---|
| 数据模型 | PostgreSQL 关系型,约 30 张表 |
| API 层 | PostgREST(从 eq. 语法、Content-Range、Prefer: count=exact 判定) |
| 文档 | Swagger UI 2.0,/swagger-initializer.js 指向 /v1/ |
| 迁移管理 | Flyway(flyway_schema_history 端点暴露) |
| 等位基因命名 | 依赖 PharmVar(星号等位的官方命名机构) |
| 文献标识 | PMID(PubMed),publication 表 1,155 条 |
| 药物标识 | RxNorm(RxNorm:38400),美国 NLM 标准 |
| 基因标识 | HGNC + Entrez + Ensembl 三套并列 |
溯源链的完整形态(以一条推荐为例):
recommendation.id = 8479701
→ guidelineid = 100421
→ guideline.name = "<指南名>"、guideline.url = "https://www.clinpgx.org/guideline/PA..."
→ drugid = "RxNorm:190521"
→ drug.name = "abacavir"、drug.drugbankid、drug.atcid、drug.umlscui
→ publication 表(通过 guideline 关联)
→ PMID → PubMed 原文
四套 ID 并存的实用价值:drug 表同时给 RxNorm / DrugBank / ATC / UMLS,gene 表同时给 HGNC / Entrez / Ensembl / ClinPGx。做跨库 join 时,这是最省事的一层——不用自己维护 ID 映射表,CPIC 已经给好了。
但要注意 ATC 的粒度问题。ATC 是「解剖治疗化学分类」,一个 ATC 码常常对应一类药而不是一个药。
drug表里多条记录共享一个 ATC 码是正常的,不能用 ATC 码当药物主键。药物主键必须用drugid(RxNorm)。
§4 记录结构与字段字典
§4.1 一条推荐记录的解剖
实测 recommendation 表第 1 条(阿巴卡韦 × HLA-B):
{
"id": 8479701,
"guidelineid": 100421,
"drugid": "RxNorm:190521",
"implications": {"HLA-B": "Low or reduced risk of abacavir hypersensitivity"},
"drugrecommendation": "Use abacavir per standard dosing guidelines",
"classification": "Strong",
"phenotypes": {},
"activityscore": {},
"allelestatus": {"HLA-B": "HLA-B*57:01 negative"},
"lookupkey": {"HLA-B": "*57:01 negative"},
"population": "general",
"comments": "n/a",
"version": 1,
"dosinginformation": false,
"alternatedrugavailable": false,
"otherprescribingguidance": false
}
逐字段判读:
| 字段 | 值 | 含义 | 陷阱 |
|---|---|---|---|
implications |
{HLA-B: "Low or reduced risk..."} |
临床含义,按基因名索引 | 是对象不是字符串 |
drugrecommendation |
"Use abacavir per standard..." |
推荐正文 | 英文祈使句,长度不定 |
classification |
Strong |
推荐强度 | 五档,不是四级 |
phenotypes |
{} |
空对象 | 字段名有误导性,见下 |
activityscore |
{} |
空 | 只有 CYP 系基因用 |
allelestatus |
{HLA-B: "HLA-B*57:01 negative"} |
触发条件 | 这才是真正的匹配键 |
lookupkey |
{HLA-B: "*57:01 negative"} |
简化匹配键 | 与 allelestatus 内容重复但格式不同 |
dosinginformation |
false |
本条是否含具体剂量 | 布尔值,判「有没有剂量」用这个 |
alternatedrugavailable |
false |
是否有替代药 | 布尔值 |
version |
1 |
编辑次数 | 不是发布日期 |
phenotypes字段名是个陷阱。直觉上它应该装「表型值」(如Poor Metabolizer),实际上它装的是「用哪个字段名做匹配」。真正的表型值在allelestatus或activityscore里。实测这条记录phenotypes是空对象{},因为 HLA-B 走的是等位基因状态而不是代谢表型。判读规则:
allelestatus非空 → 按等位基因匹配(HLA、G6PD、RYR1 这类);activityscore非空 → 按活性评分匹配(CYP2D6、CYP2C9 这类)。两者通常互斥。
§4.2 只有 22 个基因有等位基因级定义
这是一个必须写在最前面的结构事实:
| 层级 | 基因数 | 说明 |
|---|---|---|
gene 表收录 |
132 | 全部 |
allele 表有等位基因 |
22 | 16.7% |
diplotype 表有双倍型 |
18 | 13.6% |
110 个基因(83.3%)只有药-基因对层面的信息,没有等位基因级细化。 它们长这样:
| 有等位的基因(22 个) | 只有对的基因(典型) |
|---|---|
| CYP2D6、CYP2C9、CYP2C19、CYP2B6、CYP3A5、CYP4F2、DPYD、TPMT、NUDT15、SLCO1B1、NAT2、G6PD、HLA-A/B、RYR1、CFTR、CACNA1S、IFNL3、UGT1A1、VKORC1、F5 | HMGCR(他汀)、CHRNA3(吸烟)、MTRR(叶酸)、COMT、OPRM1、HTR2A、ADRB1、SLC6A4…… |
为什么有这个差别:只有当「同一基因的不同等位导致不同的处方决策」时,才值得做等位基因级定义。
CYP2D6必须做:*1/*1(正常)与*4/*4(无功能)的可待因用量完全不同。HMGCR不必做:他汀的疗效与 HMGCR 变异有关,但目前没有证据支持按基因型调整他汀剂量,所以只到「药-基因对」层面。
这个结构直接决定了数据集的用法:只有 22 个基因能做「基因型 → 表型」的监督学习,其余 110 个只能做「基因-药关联」的弱标签。做双倍型映射模型时,类别数是 22 而不是 132,这个数字如果搞错,整个任务定义都是错的。
另一面:allele_definition 表 1,354 条,比 allele 的 1,378 条略少(差 24)。这个表才是「哪些 SNP 组合构成这个星号等位」的定义,是做基因型判定(从 VCF 到星号)的必要输入。少 24 条是因为部分等位(如 *5 全基因缺失)没有 SNP 定义——它们靠拷贝数检测,不是靠位点。
§4.3 双倍型表:112,820 条映射的真相
diplotype 表是这个库最大的表,也是坑最多的表。实测一条:
{
"genesymbol": "CFTR",
"diplotype": "D110H/L1480P",
"function1": "ivacaftor responsive",
"function2": "ivacaftor responsive",
"activityvalue1": "n/a",
"activityvalue2": "n/a",
"totalactivityscore": "n/a",
"description": "An individual homozygous or compound heterozygous for a CFTR variant...",
"diplotypekey": {"CFTR": {"D110H": 1, "L1480P": 1}},
"generesult": "ivacaftor responsive in CF patients",
"ehrpriority": null,
"consultationtext": null,
"lookupkey": {"CFTR": "ivacaftor responsive in CF patients"}
}
三个必须知道的事实:
事实一:totalactivityscore 是字符串,且大量是 n/a。
我们把 5 个主要基因单独统计:
| 基因 | 抽样行数 | totalactivityscore 为 n/a |
占比 |
|---|---|---|---|
| CYP2C19 | 666 | 666 | 100.0% |
| TPMT | 1,225 | 1,225 | 100.0% |
| CYP2C9 | 2,850 | 2,184 | 76.6% |
| CYP2D6 | 3,000 | 1,491 | 49.7% |
| DPYD | 3,570 | 0 | 0% |
同一个字段,在 CYP2C19 上 100% 是字符串 n/a,在 DPYD 上 100% 是数值。 这说明 totalactivityscore 只对「有加性活性模型」的基因有意义(CYP2D6、CYP2C9、DPYD 用活性值加和),对不适用加性模型的基因(CYP2C19 按表型直接分级、TPMT 按酶活性分级)就填 n/a。
这不是数据质量问题,是模型差异。CYP2D6 的活性评分是「两个等位的活性值相加」(
*1=1、*4=0,所以*1/*4=1.0),这个加性假设成立;CYP2C19 的表型不能这么算(*2/*17的组合不是简单相加),所以干脆不给数值。把它当连续变量做回归,会把 82.3% 的样本丢掉。
事实二:等位基因名在 diplotype 字段里不一定是星号。 CFTR 用的是 D110H/L1480P(氨基酸变异命名),G6PD 用的是 B/A- 这类传统命名,只有 CYP 系才用 *4/*4。解析双倍型字符串时不能假设一定有 *。
事实三:ehrpriority 在我们抽样的 9,741 行里 100% 非空(即都有值),而单独查第 1 条 CFTR 记录时是 null。这说明该字段在不同基因上填充率差异很大——不能假设全表都有。
§4.4 药-基因对的四个判读字段
pair 表 635 条,四个字段决定「这对有没有用」:
| 字段 | 取值分布 | 判读 |
|---|---|---|
usedforrecommendation |
true 136(21.4%) / false 499(78.6%) | 最有用的一个字段:这对是否真用于出推荐 |
cpiclevel |
A 96 / B 36 / B/C 56 / C 284 / C/D 15 / D 134 | 证据强度 |
clinpgxlevel |
1A 103 / 2A 19 / 2B 21 / 3 219 / 4 18 / 空 247(38.9%) | ClinPGx 侧的分级,38.9% 是空的 |
pgxtesting |
空 460(72.4%) / Actionable 84 / Informative 57 / Testing Required 15 / Testing Recommended 9 / No Clinical PGx 10 | 检测建议 |
pgxtesting 的 72.4% 空值是最容易被误读的地方。 空不等于「不建议检测」,空的意思是「这对没有明确的检测建议标签」。真正的检测建议要看非空的 28%:
Testing Required(15 条):必须测,不测不能用药。Testing Recommended(9 条):建议测。Actionable PGx(84 条):检测结果可指导用药。Informative PGx(57 条):有信息价值但通常不改处方。No Clinical PGx(10 条):认为无临床价值。
只有 24 条(15 + 9)是「该测」级别的。这个数字比多数人预期的低得多。
removed 字段:61 条(9.6%)为 true。 这意味着每十个药-基因对里就有一个已被撤回。撤回原因在 removedreason 字段。不处理 removed 会引入 61 条已废弃的关联,这是最容易犯的错。
§4.5 药物表:98 张流程图
drug 表 324 条,几个有用的字段:
| 字段 | 覆盖 | 说明 |
|---|---|---|
drugid |
324(100%) | 主键,RxNorm:xxxx |
name |
324 | 药物名(如 fluticasone/salmeterol 复方也单列一条) |
rxnormid / drugbankid / atcid / umlscui |
大部分 | 四套外部 ID |
flowchart |
98(30.2%) | 临床决策流程图 JPG 的 URL |
guidelineid |
部分 | 关联指南 |
98 张流程图是这个库被低估的资产。每张是一份把「基因型 → 表型 → 剂量」画成流程图的位图(如 Atomoxetine_CDS_Flow_Chart.jpg、G6PD_High_Risk_Drug_CDS_Flow_Chart.jpg)。它们不在 recommendation 表的文本里,是补充材料。
只有 30.2% 的药物有流程图,原因是流程图是较晚才开始做的(指南更新时补)。老指南只有文字推荐、没有图。 所以「有图」可以作为「这条指南被较新地修订过」的弱信号。
另一个细节:fluticasone/salmeterol(氟替卡松/沙美特罗复方)单独占一条记录。CPIC 收录的是「处方药」,不是「活性成分」,所以复方制剂会单独列出。按活性成分 join 会漏掉这类记录。
§4.6 一张被忽略的表:test_alert 2,213 条
test_alert 是 CPIC 里最接近「产品」的一张表——它不是给研究者看的,是给 EHR 系统直接调用的。
| 字段 | 内容 |
|---|---|
cdscontext |
Pre-test(检测前)/ Post-test(检测后) |
genes |
涉及的基因数组,可以是多个 |
phenotype / activityscore / allelestatus |
触发条件(三者组合) |
lookupkey |
匹配键 |
alerttext |
警示正文,字符串数组,可直接显示 |
population |
适用人群 |
为什么它值钱:recommendation 表的 drugrecommendation 是给指南读者看的短句(Use abacavir per standard dosing guidelines),而 alerttext 是给临床医生在诊室里看的完整段落——它会把「为什么」「怎么办」「如果没测怎么办」都写进去。
实测一条完整的 alerttext(阿米替林 × CYP2D6 + CYP2C19):
“CYP2D6 and CYP2C19 genetic status may be predictive of an adverse reaction or poor response to this medication due to altered drug metabolism. This patient is predicted to be a CYP2D6 poor metabolizer and may be at an increased risk of a sub-optimal response. Consider selecting an alternative drug not metabolized by CYP2D6. If amitriptyline is warranted, consider a 50% reduction of recommended starting dose and utilize therapeutic drug monitoring to guide dose adjustments. A CYP2C19 genotype does not appear to have been ordered for this patient. CYP2C19 genetic status may be important for alternative drugs. Please consult a clinical pharmacist for more information.”
这一段 6 句话,结构非常完整:
- 前提声明(这两个基因与药效相关)
- 患者状态(CYP2D6 慢代谢)
- 风险(疗效不足)
- 首选方案(换不依赖 CYP2D6 的药)
- 次选方案(减 50% 起始剂量 + 治疗药物监测)
- 缺失信息的处理(CYP2C19 未检测,且提示它对替代药也重要)
- 兜底(咨询临床药师)
第 6 句是整段最值得学的:它没有假设数据完整,而是显式处理了「某个基因没测」这个真实场景。绝大多数「AI 生成用药建议」的失败案例,正是因为没有这种兜底逻辑——输入缺字段就瞎猜。这 2,213 条文本是「如何在信息不全时给建议」的现成范本。
§5 检索、抽样与泄漏分析
§5.0 五种可用的检索方式
一、拿全表(PostgREST 标准语法)
# 拿全部推荐,只取需要的列
curl -s "https://api.cpicpgx.org/v1/recommendation?select=id,guidelineid,drugid,classification,drugrecommendation" \
-o recs.json
二、按条件过滤(eq. 前缀)
# 只拿 A 级药-基因对
curl -s "https://api.cpicpgx.org/v1/pair?cpiclevel=eq.A&select=genesymbol,drugid,cpiclevel"
# 只拿 CYP2D6 的双倍型
curl -s "https://api.cpicpgx.org/v1/diplotype?genesymbol=eq.CYP2D6&limit=5000"
三、只数条数,不拿数据(最省流量的技巧)
# PostgREST 的 count=exact:只读响应头,不下载正文
curl -s -I "https://api.cpicpgx.org/v1/diplotype" \
-H "Prefer: count=exact" -H "Range: 0-0" | grep -i content-range
# → content-range: 0-0/112820
四、用预连接视图省掉 join
# recommendation_view 已经把 guideline 与 drug 连好
curl -s "https://api.cpicpgx.org/v1/recommendation_view?limit=5"
五、用 rpc 存储过程(少见但有用)
# 4 个 rpc:recommendation_lookup、test_alert_lookup、
# clinpgx_guideline_recommendation、clinpgx_guideline_alleles
curl -s "https://api.cpicpgx.org/v1/rpc/recommendation_lookup?..."
Prefer: count=exact+Range: 0-0这一招值得记住。它让 PostgREST 只返回「第 0 条到第 0 条」的内容,但在Content-Range头里给出总行数。统计一个百万级表有多少行,只需要几百字节流量。 本篇所有行数都是这么测的。
§5.1 抽样策略:按基因切,不按行切
CPIC 的表结构很特殊:行之间不是独立的,是「按基因聚簇」的。
| 表 | 聚簇结构 | 正确抽样方式 |
|---|---|---|
diplotype |
按 genesymbol 聚簇(18 个基因) |
按基因全取,不要跨基因随机抽 |
allele |
按 genesymbol 聚簇(22 个基因) |
同上 |
recommendation |
按 guidelineid 聚簇(29 部指南) |
按指南全取 |
test_alert |
按 drugid 聚簇 |
按药物全取 |
allele_frequency |
按等位基因聚簇 | 按基因全取 |
为什么不能随机抽样:如果随机抽 1,000 条双倍型,抽到的可能 90% 都来自 CYP2D6(因为它有几千行),G6PD、RYR1 这些「行数少但临床极重要」的基因会完全消失。按基因全取,每个基因的完整映射表才是可用的。
我们的实测就是这么做的:132 个基因逐个拉取(
genesymbol=eq.<gene>),3 分 46 秒拿到 30,611 行,覆盖 18 个有双倍型的基因。没有一个基因被漏掉,只是每个基因内部受limit上限截断。
§5.2 四类真实泄漏
药物基因组学数据集的泄漏问题与影像、序列类数据集完全不同,因为它的样本是「规则」而不是「观测」。
第一类:同一指南内的推荐跨侧(最严重)
一部指南(如「CYP2D6 与阿片类」)会给同一药物的多个基因型分别写推荐:*1/*1 用标准剂量、*1/*4 减量、*4/*4 换药。这几条推荐是同一个作者、同一批证据、同一次评议的产物。
把同一指南的推荐随机分到训练和测试,模型学到的是「这部指南的措辞风格」,而不是「从基因型推剂量」。 正确做法:按 guidelineid 分组划分,29 部指南最多 29 折。
第二类:同基因不同药的跨侧(隐蔽)
CYP2D6 涉及 81 个药-基因对。「CYP2D6 慢代谢 + 可待因」与「CYP2D6 慢代谢 + 曲马多」的推荐逻辑几乎一样(都是「前药活化不足,疗效差」)。
如果按药物随机划分,模型会学到「CYP2D6 PM 一律疗效差」这条捷径,在测试集上分数很高,但换到新基因就崩。正确做法:按基因分组划分(22 个基因最多 22 折),或者同时按基因和指南分组(更严)。
第三类:recommendation 与 test_alert 的文本重叠(极易忽略)
test_alert.alerttext 里的句子,大量是从 recommendation.drugrecommendation 扩写来的。同一条规则,在这两张表里各有一份表述。
如果拿 recommendation 训练、拿 test_alert 测试(或反过来),测的是「模型能不能记住改写」,不是「能不能推理」。 正确做法:划分时按「规则」而不是按「表」——同一条规则的两种表述必须在同一侧。
第四类:diplotype 表内部的组合爆炸(结构性)
CYP2D6 有 208 个等位,双倍型组合数是 208 × 209 / 2 ≈ 21,736 种。但 diplotype 表里 CYP2D6 只有几千行——因为只有「有意义」的组合才被列出(两个无功能等位的组合归为同一表型,不再细分)。
这意味着:diplotype 表不是「全部可能基因型」,是「全部需要区分的基因型」。用它训练时,测试集里的新组合可能落在训练集见过的表型类别里——这是设计使然,不是泄漏,但会让「分类准确率」虚高。必须报「按表型类别分层的准确率」,而不是总体准确率。
§5.3 结构泄漏:从元数据本身推断出的信息
最典型的一种:lookupkey 字段泄露答案。
recommendation.lookupkey 与 allelestatus 内容高度重合:
allelestatus: {"HLA-B": "HLA-B*57:01 negative"}
lookupkey: {"HLA-B": "*57:01 negative"}
如果你的任务是从基因型预测推荐,而 lookupkey 在输入特征里,模型只需要匹配字符串就能拿到答案——因为 lookupkey 就是这张表的匹配主键。
处置:
id、lookupkey、version、diplotypekey这几个字段在任何预测任务里都必须从特征中剔除。它们不是「信息」,是「主键的另一种写法」。
第二种:description 字段直接说出了结论。
diplotype.description 的实测值:
“An individual homozygous or compound heterozygous for a CFTR variant listed in the FDA-approved drug label as being responsive to ivacaftor”
这句话里已经包含了 generesult 的答案(“ivacaftor responsive”)。用 description 当输入、generesult 当标签,等于把答案抄进题干。
§5.4 一个不该做的划分:按药物切
有人会想「按药物划分最公平,模型没见过这个药」。这在 CPIC 上不成立,原因是:
324 个药物里,只有 96 对是 A 级,只涉及 78 个药物。 其中 CYP2D6 一个基因就占 81 对(12.8%),CYP2C19 占 27 对、CYP2C9 占 26 对。
按药物切会导致:
- 训练集里 CYP2D6 相关的药很多,测试集里可能一个都没有 → 测试集退化成「全是罕见基因」。
- 反过来,测试集里 CYP2D6 的药很多,训练集几乎没有 → 模型在测试集上全错。
正确做法:按基因分组划分(GroupKFold by genesymbol),并在每个折内报告「该折包含哪些基因」。这样即使某折只有 1-2 个基因,你也知道这个折的分数代表什么。
§6 AI 就绪指南
§6.1 最小可用 Pipeline
import requests, json, time
BASE = "https://api.cpicpgx.org/v1"
def fetch(table, select=None, params=None, limit=5000, max_retry=3):
"""按 PostgREST 语法拉一页,带重试"""
q = {"limit": limit}
if select: q["select"] = select
if params: q.update(params)
for i in range(max_retry):
try:
r = requests.get(f"{BASE}/{table}", params=q, timeout=120)
if r.status_code == 200:
return r.json()
except Exception as e:
print(f" retry {i+1}: {e}")
time.sleep(2 ** i)
return []
def count(table):
"""只读 Content-Range 头拿总行数,不下载正文"""
r = requests.head(f"{BASE}/{table}",
headers={"Prefer": "count=exact", "Range": "0-0"},
timeout=60)
return int(r.headers["content-range"].split("/")[1])
四个关键点:
- 统计行数用
HEAD+Range: 0-0,不要GET全表。 - 大表按基因切(
diplotype、allele、allele_frequency),不要一次拉全表——实测 112,820 条一次拉 7 分钟不返回。 limit设 5,000,超过这个量服务端会变慢但不会报错(静默变慢是最难查的故障)。*_view端点优先:recommendation_view、pair_view、population_frequency_view已连好表,省掉自己写 join。
§6.2 构建训练样本
任务一:基因型 → 表型(分类)
# 输入:diplotype.diplotype 字符串(如 "*4/*4"、"B/A-")
# 标签:diplotype.generesult(如 "Poor Metabolizer")
# 类别数:**22 个基因 × 各自 4-5 档表型**,不是全局统一类别
# 注意:CFTR 用氨基酸命名、G6PD 用 A-/B 命名、CYP 系用星号
# 解析器必须按基因分派,不能写一套正则搞定全部
任务二:药-基因对 → 是否用于推荐(二分类)
# 输入:genesymbol + drugid(需 embedding)
# 标签:pair.usedforrecommendation(136 true / 499 false)
# 这是**严重不平衡**(1:3.7),必须用 AUC-PR 而不是 AUC-ROC
# 坑:removed=true 的 61 条必须从标签里剔除,否则学到的是"已废弃关联"
任务三:推荐正文生成 / 强度判别
# 输入:基因型条件(allelestatus 或 activityscore)+ 药物名
# 标签:recommendation.classification(Strong/Moderate/Optional/No Rec)
# 或:drugrecommendation 正文(生成任务)
# 注意:按 guidelineid 分组划分,否则学到措辞风格
三个任务共同的坑:必须剔除 id / lookupkey / version / diplotypekey / description 这几个字段(见 §5.3)。description 尤其危险——它常常直接写出 generesult 的答案。
§6.3 评价指标
| 任务 | 主指标 | 为什么 |
|---|---|---|
| 基因型 → 表型 | 按基因分层的 macro-F1 | 22 个基因,不按基因分层会被 CYP2D6 主导 |
| 是否用于推荐 | AUC-PR + 在召回 90% 时的精确率 | 1:3.7 不平衡,ROC 会虚高 |
| 推荐强度判别 | 四类混淆矩阵 + Optional 的召回 | Optional 占 49.5%,模型会全predict 它 |
| 推荐正文生成 | 人工评估 + BLEU 仅作参考 | 临床文本,BLEU 与可用性相关性很差 |
必须报告的分层:
- 按基因(CYP2D6 vs 其他):CYP2D6 占数据 12.8%,不分层会被它主导。
- 按证据等级(A vs C):A 级只有 96 对,C 级 284 对,混在一起报均值毫无意义。
- 按
totalactivityscore是否可用:CYP2C19/TPMT 100% 是n/a,DPYD 0%,这两类数据的可用特征完全不同。
一个必须避免的指标误用:不要报「双倍型映射准确率」的整体数字。因为
diplotype表只列「有意义的组合」,大部分新组合会落在已知表型类别里,准确率天然很高(可能 95%+),但这个数字不反映模型对新颖基因型的泛化能力。要报就报**「留一基因」交叉验证**下的准确率——那才是真实泛化。
§6.4 MLOps:怎么钉住版本
CPIC 没有版本号、没有快照,所以钉版本只能靠自己。 推荐配置:
dataset:
source: CPIC
base_url: "https://api.cpicpgx.org/v1"
snapshot_date: "2026-10-23"
# 注意:cpicpgx.org 已于 2025-07-30 重定向到 clinpgx.org
# 但 api.cpicpgx.org 仍在服务,需监控其可用性
counts:
gene: 132
drug: 324
guideline: 29
pair: 635
allele: 1378
recommendation: 2115
diplotype: 112820
content_hash:
recommendation: "<对 2115 条按 id 排序后序列化的 SHA256>"
diplotype: "<对 112820 条按 genesymbol+diplotype 排序后的 SHA256>"
filters_applied:
drop_removed: true # 剔除 pair.removed = true 的 61 条
drop_na_classification: true # 剔除 classification = "n/a" 的 12 条
splits:
strategy: "GroupKFold by genesymbol"
n_folds: 22
field_exclusions: # 见 §5.3,必须剔除
- id
- lookupkey
- diplotypekey
- version
- description
两个最关键的行:
snapshot_date+content_hash:CPIC 会随时改,没有哈希你无法证明「训练用的是哪一版」。field_exclusions:把泄漏字段写进配置,比写在代码注释里可靠。
还应该加一个「域名存活监控」。
api.cpicpgx.org是旧域名延续服务,官方新方向是 ClinPGx 的 API(路径不同,/v1/gene返回 404)。如果某天api.cpicpgx.org下线,你的 pipeline 会突然全断,且不会有任何预告。定期探测HEAD /v1/gene是否仍返回 200,并准备 ClinPGx 侧的迁移方案。
§6.5 六个坑点
坑点 1:把 635 个药-基因对当成「635 条可用推荐」
recommendation 表只有 2,115 条,但 pair 表 635 对里 usedforrecommendation = true 的只有 136 对。剩下的 499 对(78.6%)有相关性,但没有落到处方建议。 用 pair 表当「推荐数据集」,会把大量「有研究但无建议」的对误标成「有建议」。
正确做法:先按
usedforrecommendation = true过滤,再 joinrecommendation。136 对 → 2,115 条推荐,这个映射不是一对一(一对药-基因通常有多条推荐,因为要覆盖多个基因型)。
坑点 2:totalactivityscore 当数字用
实测:CYP2C19、TPMT 的 totalactivityscore 100% 是字符串 n/a;CYP2C9 76.6%、CYP2D6 49.7% 也是 n/a;只有 DPYD 0% 是 n/a。
# 错误写法:直接转 float,会崩溃
score = float(row['totalactivityscore']) # ValueError: could not convert 'n/a'
# 正确写法:显式区分
v = row['totalactivityscore']
score = None if v in ('n/a', None, '') else float(v)
更严重的问题是用错了模型假设:totalactivityscore 只对「加性活性模型」成立的基因有意义(CYP2D6、CYP2C9、DPYD),对 CYP2C19、TPMT 这类「按表型直接分级」的基因根本不该有值。把它当全库统一的连续特征,会丢掉 82.3% 的样本(按我们抽样)。
坑点 3:clinicalfunctionalstatus 当枚举处理
这个字段名义上五档(正常/减/无/增加/不确定),实测有 18 种不同写法,包括:
Uncertain function(384 条)与Unknown function(52 条)是两个不同概念,不能合并。ivacaftor responsive(103 条)不是功能状态,是 CFTR 的药物响应标签。I/Deficient with CNSHA、II/Deficient(G6PD 的 WHO 分级)是另一套体系。
正确做法:按基因分组,组内映射。CYP 系基因一套规则、G6PD 一套、CFTR 单独一套。不要做全局字符串映射。
坑点 4:不处理 removed
pair 表 61 条(9.6%) 的 removed = true,原因是证据被推翻或指南撤回。drug 表没有 removed 字段(实测 ?select=removed 报错 column drug.removed does not exist)——说明只有 pair 表支持撤回,基因和药物本身不撤回。
不剔除这 61 条,等于把已废弃的医学结论喂给模型。 这在临床场景下是严重错误。
坑点 5:phenotypes 字段名骗人
"phenotypes": {} ← 空对象,不是表型值
"allelestatus": {"HLA-B": "HLA-B*57:01 negative"} ← 真正的匹配条件在这里
phenotypes 装的是「用哪个字段做匹配」,不是「匹配到什么值」。 实测第一条推荐记录 phenotypes 是空 {},因为 HLA-B 走等位基因匹配。按字段名猜语义,在这里必然出错。
坑点 6:api.cpicpgx.org 与 api.clinpgx.org 不是同一套 API
| 域名 | 路径 | 实测 |
|---|---|---|
api.cpicpgx.org |
/v1/gene |
200,返回 CPIC 表结构 |
api.clinpgx.org |
/v1/gene |
404({"status":"fail","data":{"errors":[{"message":"HTTP 404 Not Found"}]}}) |
ClinPGx 的 API 存在,但用的是完全不同的资源名(chemical、guidelineAnnotation、variantAnnotation、label、pathway),没有 /gene 这个路径,也没有 allele 资源(星号等位在 PharmVar)。
照着「ClinPGx 是 CPIC 的新家」这句话去改代码,会立刻踩 404。 两个体系的表结构不兼容,不是换域名就完事。
§6.6 反模式清单
| 反模式 | 为什么错 | 正确做法 |
|---|---|---|
用 pair 表当推荐数据集 |
78.6% 的对没有推荐 | 先过滤 usedforrecommendation |
随机划分 recommendation |
同指南的推荐跨侧 | 按 guidelineid 分组 |
随机划分 diplotype |
同基因的双倍型跨侧 | 按 genesymbol 分组 |
用 description 当特征 |
它常含 generesult 的答案 |
剔除(见 §5.3) |
用 lookupkey 当特征 |
它就是匹配主键 | 剔除 |
把 totalactivityscore 转 float |
82.3% 是 n/a |
显式判空 + 只用于加性模型基因 |
| 全局字符串映射功能状态 | 18 种写法,3 套语义 | 按基因分组映射 |
| 用 ROC-AUC 报药-基因对分类 | 1:3.7 不平衡 | 用 AUC-PR |
假设双倍型都是 *4/*4 格式 |
CFTR 用 D110H/L1480P |
按基因分派解析器 |
| 假设 API 域名稳定 | 旧域名延续服务,随时可能下线 | 加存活监控 |
§7 质量评估、DAIMS 与口径交叉核对
§7.1 记录级质量
CPIC 没有「质量分数」字段,但有六个隐含的质量信号:
| 信号 | 字段 | 判读 |
|---|---|---|
| 证据等级 | pair.cpiclevel |
A > B > B/C > C > C/D > D |
| 是否用于推荐 | pair.usedforrecommendation |
true 才真正产出建议 |
| 推荐强度 | recommendation.classification |
Strong > Moderate > Optional > No Rec |
| 是否含剂量 | recommendation.dosinginformation |
true 才是「可执行」的剂量建议 |
| 是否有替代药 | recommendation.alternatedrugavailable |
true 说明给了退路 |
| ClinPGx 分级 | pair.clinpgxlevel |
有 38.9% 是空的,空值不可判 |
最实用的组合判据是 classification = Strong + dosinginformation = true——这代表「强推荐且给了具体剂量」,是可以直接当处方规则的那一小批。
注意
dosinginformation只有布尔值,不给剂量本身。 实测阿巴卡韦那条dosinginformation = false,因为推荐是「按标准剂量用」,不需要调整。false不等于「没建议」,可能恰恰是「不用改」。 判读时要结合drugrecommendation文本。
§7.2 抽样声明:本条目数字的边界
| 数字类别 | 来源 | 边界 |
|---|---|---|
| 七个主表行数(132/324/29/635/1,378/2,115/112,820) | HEAD + Prefer: count=exact |
精确,服务端计数 |
| 其余表行数(2,213/1,155/3,917/387,734/907) | 同上 | 精确 |
recommendation.classification 分布 |
2,115 条全量 | 精确(全表拉取) |
pair 各字段分布 |
635 条全量 | 精确 |
allele 功能状态分布 |
1,378 条全量 | 精确 |
population 族裔分布 |
3,917 条全量 | 精确 |
diplotype.totalactivityscore 的 n/a 比例 |
按基因抽样 30,611 / 112,820(27.1%) | 抽样,非全量 |
drug.flowchart 覆盖 98/324 |
324 条全量 | 精确 |
最重要的一条边界:
diplotype表我们只拿到 30,611 行(27.1%)。 原因是全量一次拉取超时(7 分钟未返回),改为按基因逐个拉取时每个基因受limit=5000截断(CFTR、CYP2D6、G6PD、RYR1 四个基因各返回满 5,000 行,明显被截断)。所以 §4.3 里「82.3% 是 n/a」这个数字是这 30,611 行的比例,不是全库 112,820 行的比例。 但按基因分层的抽样(CYP2C19 100%、TPMT 100%、DPYD 0%)本身信息量足够说明「不同基因差异极大」这个结论。
§7.3 三个必须知道的临床效度问题
第一,「有推荐」不等于「该检测」。 这是最常被混淆的一点。cpiclevel = C 的 284 对(44.7%)意味着「证据不足以支持常规检测」,但如果病人已经测了,CPIC 仍然会给出基因型对应的建议。「该不该测」和「测了怎么办」是两个独立判断,数据里分别由 pgxtesting 和 classification 承载。
第二,CPIC 的推荐不覆盖药物相互作用。 一个人基因型是 CYP2D6 正常代谢者,但如果同时服用强效 CYP2D6 抑制剂(如帕罗西汀),其实际表型会变成慢代谢者——这叫表型转换(phenoconversion)。CPIC 的 diplotype 表只给基因型决定的表型,不含药物诱导/抑制的影响。
这也是 ClinPGx 后来推出 PharmDOG 工具(带表型转换计算器)的原因。光有遗传表型,在真实多药患者身上是不够的。
第三,检测方法本身有盲区。 allele 表列了 1,378 个等位,但没有任何一款检测 panel 能全部区分。常见 panel 覆盖 20-50 个核心位点,结构变异(*5 全基因缺失、*2xN 重复)尤其容易被漏检。如果你的输入是 panel 结果而不是全基因组测序,很多星号等位根本没被测到,此时套用 CPIC 的表型映射会得出错误结论。
§7.4 偏倚清单(可核查)
| 偏倚 | 证据 | 影响 |
|---|---|---|
| 证据集中于少数基因 | CYP2D6 一基因占 81/635 对(12.8%) | 模型会过度拟合 CYP2D6 |
| A 级覆盖窄 | 仅 96 对、78 个药 | 「高置信」样本量极小 |
| 等位基因级只覆盖 22 基因 | 132 中仅 22 | 110 个基因无法做基因型级建模 |
| 人群以欧洲裔为主 | population 中 European 29.6% |
东亚 23.6% 尚可,非洲裔仅 12.8% |
| 推荐以英文为主 | drugrecommendation 全英文 |
中文场景需翻译,术语易失真 |
| Optional 占一半 | 1,047/2,115(49.5%) | 「有推荐」不等于「有明确建议」 |
| 撤回率 9.6% | pair.removed 61 条 |
不处理会引入已废弃结论 |
「Optional 占 49.5%」这一条值得展开。这意味着如果随机抽一条 CPIC 推荐,一半的概率是「可选,获益不确定」。用它训练「用药建议生成」模型,模型会学到大量「可以考虑……也可以不……」的模糊表述。如果目标是「给出明确建议」,必须先按
classification过滤到 Strong 或 Moderate(948 条,44.8%)。
§7.5 数据完整性核查表
动手前的八分钟检查:
- [ ] 是否用
HEAD+Range: 0-0核过行数(而不是猜)? - [ ]
pair表是否已按removed过滤掉 61 条? - [ ]
recommendation是否已按usedforrecommendation过滤到 136 对? - [ ]
totalactivityscore是否做了n/a判空? - [ ]
clinicalfunctionalstatus是否按基因分组映射? - [ ] 双倍型解析器是否覆盖了非星号格式(CFTR / G6PD)?
- [ ] 划分是否按
guidelineid或genesymbol分组? - [ ]
id/lookupkey/diplotypekey/version/description是否已从特征剔除?
§7.6 DAIMS 24 项逐项评分
| # | 维度 | 判定 | 说明 |
|---|---|---|---|
| 1 | 数据集有唯一标识 | ✅ | 各表有主键(id / drugid / genesymbol / pairid) |
| 2 | 有版本标识 | ⚠️ | 无全库版本号,仅记录级 version |
| 3 | 有持久标识符 | ✅ | guideline.url 指向 ClinPGx 的 PA 号,稳定 |
| 4 | 有许可声明 | ✅ | CC0 / 公有领域,官网明示 |
| 5 | 有引用规范 | ⚠️ | 官网有出版物列表,但无统一 CITATION 文件 |
| 6 | 有数据字典 | ✅ | Swagger/OpenAPI 规范完整列出 34 端点字段 |
| 7 | 有记录级元数据 | ✅ | 每条推荐带 guidelineid / drugid / version |
| 8 | 有来源溯源 | ✅ | publication 表 1,155 篇 PMID,逐指南可溯 |
| 9 | 有采集方法说明 | ✅ | 官网详述证据分级流程与同行评议 |
| 10 | 有质量控制说明 | ✅ | 分级体系本身就是 QC 机制 |
| 11 | 有缺失值说明 | ❌ | 无文档说明 n/a 与空值的语义差异 |
| 12 | 有样本量说明 | ⚠️ | population.subjectcount 有,但全库受试者规模未汇总 |
| 13 | 有偏倚说明 | ❌ | 官网未系统说明人群偏倚 |
| 14 | 有伦理/隐私声明 | ✅ | 无个体数据,纯指南库 |
| 15 | 可公开访问 | ✅ | 无需注册、无需 token |
| 16 | 有机器可读格式 | ✅ | JSON,且是标准的 PostgREST 规范 |
| 17 | 有批量下载 | ✅ | 全表通过 API 可取;大表需分页 |
| 18 | 有 API 文档 | ✅ | Swagger UI 在线可交互 |
| 19 | 有更新日志 | ✅ | change_log 907 条,可做增量 |
| 20 | 有数据规模声明 | ✅ | 行数可通过 count=exact 精确核验 |
| 21 | 有跨库标识映射 | ✅ | drug 四套 ID、gene 四套 ID,做得很好 |
| 22 | 有语义本体对齐 | ⚠️ | 药物用 RxNorm,但功能状态字段未对齐任何本体 |
| 23 | 有可复现的划分建议 | ❌ | 无(这是数据集本身的正常缺失) |
| 24 | 有下游任务示例 | ✅ | 流程图(98 张)+ test_alert 文本即示例 |
得分:✅ 16 项 × 1 + ⚠️ 4 项 × 0.5 + ❌ 4 项 × 0 = 18.0 / 24 = 75.0%
扣分的四处,每一处都说得出具体理由:
- #2 版本标识 ⚠️:无全库版本号,只有记录级
version,且version是编辑次数不是日期。 - #11 缺失值说明 ❌:
n/a(不适用)、null(未填)、{}(空对象)三种「空」在文档里没有区分。 - #13 偏倚说明 ❌:官网未系统披露人群构成与基因覆盖偏倚。
- #23 划分建议 ❌:合理缺失——它是权威数据库,不承担 benchmark 职责。
18.0 分在已评的十一篇里处于中上位置(Rfam 91.7% > RNAcentral 85.4% > Complex Portal 79.2% > CPIC 75.0% > GBIF 58.3% = BV-BRC 58.3% > IMGT 52.1% > NeuroVault 50.0% > Alliance 47.9% > MGI 45.8% > ENA 43.8%)。它的强项是「机器可读性」——Swagger 规范、PostgREST 语法、
count=exact计数、四套外部 ID 映射,这四项做得比多数「大数据集」都好。弱项是「元数据文档」——缺失值、偏倚、版本这三件「说一说就能得分」的事它没做。
§7.7 口径交叉核对矩阵(不是模型性能验证)
对照一:pair 635 与 recommendation 2,115 不是一一对应
| 口径 | 数字 | 含义 |
|---|---|---|
pair 表总行数 |
635 | 药-基因对(含已撤回的 61 条) |
pair.usedforrecommendation = true |
136 | 真正用于出推荐的对 |
recommendation 表行数 |
2,115 | 推荐条数(一对可对应多条) |
平均每对 15.6 条推荐,但实际分布很不均:CYP2D6 相关对要覆盖大量基因型组合,所以一对能有几十条;而某些 C 级对一个基因型只有一条。
所以「635 对 / 2,115 条」这两个数不能互换使用。 说「CPIC 有 635 条推荐」是错的(少算 3.3 倍),说「CPIC 覆盖 2,115 个药-基因对」也是错的(多算 3.3 倍)。
对照二:三个「基因数」不是同一个数
| 口径 | 数字 | 含义 |
|---|---|---|
gene 表行数 |
132 | 收录的基因总数 |
allele 表涉及基因 |
22 | 有等位基因级定义的 |
diplotype 表涉及基因 |
18 | 有双倍型映射的 |
132 → 22 → 18,逐级收窄。 差的那 4 个(22 - 18)是有等位基因定义但没有双倍型映射的基因——通常是「单等位基因决定表型」的情况(如 F5 的 Factor V Leiden,一个位点就够)。
对照三:population 3,917 条 ≠ 3,917 个研究
population 表里一条记录 = 一个基因 × 一个族裔 × 一个来源的样本描述。同一个人群研究会被多个基因复用,所以3,917 是「记录数」,不是「研究数」也不是「受试者数」。
真实的受试者规模要看 subjectcount 字段,单条从几十到几千不等。汇总 3,917 条的 subjectcount 才能说「覆盖了多少人」,而这个汇总我们没有做(字段并非全部填充)。
对照四:allele 1,378 与 allele_definition 1,354 差 24 条
| 口径 | 数字 |
|---|---|
allele 表 |
1,378 |
allele_definition 表 |
1,354 |
| 差额 | 24 |
差的 24 个是「无 SNP 定义」的等位——主要是全基因缺失(如 CYP2D6*5)和拷贝数变异。它们靠拷贝数检测判定,不是靠位点组合,所以在 allele_definition 里没有对应行。
这个差异对做「VCF → 星号」的工具有直接影响:只按 SNP 位点匹配,永远判定不出
*5和*2xN。必须额外接入拷贝数检测。这是药物基因组学基因分型最容易出错的地方,也是很多开源工具的通病。
对照五:recs.json 里 classification 的分类数与文档描述
文档通常说「Strong / Moderate / Optional」三档,实测有五档:
| 值 | 条数 |
|---|---|
Optional |
1,047 |
Strong |
591 |
Moderate |
357 |
No Recommendation |
108 |
n/a |
12 |
多出来的两档共 120 条(5.7%):No Recommendation 是「明确不推荐任何调整」(这是有价值的结论,不是缺数据);n/a 是「未分级」(多为新增未评级的条目)。按三档做分类任务,会把这 120 条逼进错误的类别。
§8 生态位与相邻资源
§8.1 CPIC 在网络里的位置
┌─────────────────────────────────────────┐
│ ClinPGx(2025-07-30 起统一入口) │
│ www.clinpgx.org │
└───────┬─────────────┬─────────────┬─────┘
│ │ │
┌─────────▼───┐ ┌──────▼──────┐ ┌───▼────────┐
│ PharmGKB │ │ CPIC │ │ PharmCAT │
│ 全部证据 │ │ 已定级推荐 │ │ 基因型判定 │
└─────────────┘ └──────┬──────┘ └───┬────────┘
│ │
┌─────────────▼──┐ ┌──────▼─────────┐
│ api.cpicpgx.org│ │ PharmVar │
│ (仍在服务) │ │ 星号等位命名 │
└────────────────┘ └────────────────┘
│
┌─────────────▼──────────────┐
│ 数据来源:PubMed 文献 + │
│ 各工作组人工评议 + 同行评审 │
└────────────────────────────┘
四个关键关系:
| 关系 | 说明 |
|---|---|
| CPIC ← PharmGKB | CPIC 2009 年由 PharmGKB 与 PGRN 共同发起,早期数据托管在 PharmGKB;现两者同属 ClinPGx |
| CPIC → PharmCAT | PharmCAT 是「从 VCF 判基因型」的工具,它输出的星号等位按 PharmVar 定义,表型按 CPIC 双倍型表映射。CPIC 是 PharmCAT 的下游依赖 |
| CPIC ↔ PharmVar | PharmVar 定「什么叫 *4」(等位基因的官方定义),CPIC 定「*4/*4 该怎么办」。前者是命名,后者是解释 |
| CPIC ↔ DPWG | 两套独立的国际推荐体系,结论常有分歧,需并列而非合并 |
§8.2 与本站已收条目的关系
| 已收条目 | 关系 |
|---|---|
| PharmGKB | 原料 vs 成品。PharmGKB 收全部证据(含未分级),CPIC 只收已定级可落地的 |
| GTEx | GTEx 给「基因在组织中表达多少」,CPIC 给「这个基因的变异怎么影响用药」。表达量不能替代功能状态 |
| 1000 Genomes | 提供人群频率原始数据,CPIC 的 allele_frequency 表是「按临床关注位点重新汇总」的版本 |
| TCGA | TCGA 是「肿瘤体细胞变异 + 用药反应」,CPIC 是「胚系变异 + 用药剂量」。一个是疗效,一个是代谢 |
| MIMIC / eICU 等 EHR | EHR 记录「实际怎么用」,CPIC 记录「应该怎么用」 |
与 PharmGKB 的分工需要再强调一次:库内如果已经收了 PharmGKB,可能有人会问「为什么还要 CPIC」。答案在证据门槛:
- PharmGKB 的一条 clinical annotation 可以是 Level 4(「有病例报告支持」),依然收录。
- CPIC 的推荐必须能写成祈使句,未定级的不写。
所以两者的样本量差一个数量级,但信噪比反着来。 做训练:PharmGKB 提供覆盖面,CPIC 提供标签质量。
§8.3 为什么一个「医学数据集站」要收药物基因组学
库内医学侧的数据集(影像、生理信号、EHR、NLP)绝大多数是**「观测数据」:记录患者发生了什么。药物基因组学是少数「规范数据」**:规定应该做什么。
这两类数据在 AI 训练里的角色完全不同:
| 类型 | 例子 | 训练什么 | 失败后果 |
|---|---|---|---|
| 观测数据 | MIMIC、eICU、TCGA | 预测、表征学习 | 预测不准 |
| 规范数据 | CPIC | 指令遵循、安全边界 | 给出有害建议 |
第二类数据的稀缺性远高于第一类。中文语料里有海量病历(观测),但几乎没有权威的、可溯源的、逐条对应的用药规范。CPIC 的 2,115 条推荐 + 2,213 条警示文本,是目前最接近「中文临床 AI 安全底线」的公开参照。
它也和库内已有的基因组学条目形成「三层结构」:1000 Genomes 给变异,GTEx 给表达,CPIC 给行动。三层齐全,才构成完整的「基因 → 临床」链路。
§9 许可、伦理与合规
§9.1 许可结构
| 项 | 内容 |
|---|---|
| 许可类型 | CPIC 官网自称 “Creative Commons public domain license”(CC0 类) |
| 原文 | “CPIC resources are freely available under a Creative Commons public domain license.” |
| 要求署名 | 不强制,但学术惯例要求引用 |
| 允许商用 | 是 |
| 允许修改 | 是 |
| 允许再分发 | 是 |
注意表述的模糊性:CPIC 官网写的是「Creative Commons public domain license」,没有给出具体的 CC 版本号或法律文本链接(不像 Rfam 明确指向
COPYING里的 CC0 1.0 全文)。严格说这是一个**「意图声明」而非「许可条款」**。做商用产品时,建议保留来源标注并咨询法务,不要仅凭这句话就认为零风险。
另一处需要注意:ClinPGx(新站点)的下载文件带 LICENSE.txt,写的是 CC BY-SA 4.0(署名-相同方式共享)。这与 CPIC 的「公有领域」表述不一致——CC BY-SA 有「相同方式共享」的传染性要求。
两个域名、两套许可表述,这是真实存在的不一致。 如果你从
api.cpicpgx.org拿数据,按 CPIC 口径是公有领域;如果你从 ClinPGx 下载包拿数据,按 LICENSE.txt 是 CC BY-SA 4.0(要求衍生作品同样开源)。用哪套,取决于你的数据入口。 本篇数据来自api.cpicpgx.org。
§9.2 推荐文本的二次使用
drugrecommendation 与 alerttext 是人工撰写的临床建议文本,不是原始数据。二次使用要注意三点:
| 场景 | 风险 | 建议 |
|---|---|---|
| 直接展示给医生 | 脱离指南上下文的片段可能误导 | 必须同时给出 guidelineid 与原文链接 |
| 翻译成中文 | 术语翻译不统一(如 Poor Metabolizer 译法有多种) |
保留英文原文 + 中文对照 |
| 作为模型训练标签 | 模型可能生成「看似专业但错误」的变体 | 上线前必须有人工审核环节 |
最需要注意的是「翻译」这一项。药物基因组学的表型术语(PM / IM / NM / RM / UM)在中文里有多种译法,同一个 Intermediate Metabolizer 可能被译成「中间代谢型」「中间代谢者」「中间代谢表型」。gene_result 表(101 条)是官方的表型字典,翻译时应以它为基准,不要各自发明。
§9.3 临床决策的责任边界
这是本篇最需要立场鲜明的一节。
CPIC 是群体层面的规则,它的每一条推荐都是「对一般人群,这个基因型 + 这个药,建议这样做」。它明确不针对个体,因为:
| 不覆盖的因素 | 例子 |
|---|---|
| 药物相互作用 | 帕罗西汀抑制 CYP2D6,使正常代谢者变成慢代谢者 |
| 肝肾功能 | 严重肝病患者的药物清除率与基因型预测不符 |
| 年龄与体重 | 儿童剂量按体重算,基因型只决定「相对调整方向」 |
| 合并用药与依从性 | 实际暴露量取决于患者是否按时服药 |
| 罕见变异 | panel 未覆盖的罕见等位会导致误判 |
所以「AI 根据 CPIC 给出用药建议」这句话,在任何面向患者的场景下都是不成立的。 它可以做的是:
- ✅ 给医生看的提示(「该患者 CYP2D6 为慢代谢,可待因可能无效」)
- ✅ 教学与考试题(「CYP2D6 *4/*4 用可待因该怎么处理」)
- ✅ 模型评测的参考答案(不是模型输出,是标准答案)
- ❌ 直接给患者的建议
- ❌ 替代药师审核
- ❌ 自动开处方
一句话:CPIC 是决策支持,不是决策。把它包装成「AI 自动开药」的数据基础,是对这个资源最严重的误用。
§9.4 引用规范
CPIC 没有统一的 CITATION 文件,正确的引用方式是引用具体的指南论文,而不是「CPIC 数据库」。
| 场景 | 引用什么 |
|---|---|
| 用了某条推荐 | 引用该推荐所属指南的原始论文(guideline.url → ClinPGx 页 → PMID) |
| 用了双倍型映射 | 引用对应基因的指南 + PharmVar 的等位基因定义论文 |
| 用了 API | 引用具体指南 + 注明 api.cpicpgx.org 与访问日期 |
这与 Rfam / RNAcentral 那种「引一篇总论文就行」的模式不同。CPIC 是指南合集,每部指南是独立发表的论文,不分青红皂白引「CPIC 2019」会漏掉你用到的具体证据。
§9.5 引用规范(表型术语)
gene_result 表(101 条)是这个库最被低估的小表——它是表型的标准名称字典。
为什么重要:药物基因组学的表型有标准五档 + 大量特例。CYP 系是 PM/IM/NM/RM/UM 五档,G6PD 是 WHO 四级,CFTR 是「responsive/non-responsive」,RYR1 是「MH susceptibility」。做跨基因的数据集,必须有一张表告诉你「这个基因用哪套术语」,否则你会把 G6PD 的「II/Deficient」和 CYP2D6 的「PM」硬凑成同一列。
gene_result就是这张表。 101 条记录,覆盖 22 个基因的所有合法表型名。做数据清洗时,第一步应该是用它做校验——凡是generesult不在gene_result里的,都是需要人工看的异常值。
§10 复用边界与跨条目协作手册
§10.1 决策树:什么时候该用 CPIC
你的问题是什么?
│
├─ 「某基因与某药有没有关联」
│ └─→ 用 PharmGKB / ClinPGx 全库,不要用 CPIC(CPIC 只收已定级的)
│
├─ 「某基因型用某药该给多少剂量」
│ └─→ ✅ 用 CPIC。先查 pair(usedforrecommendation=true),再查 recommendation
│
├─ 「某基因的两个等位组合是什么表型」
│ └─→ ✅ 用 CPIC 的 diplotype 表(但要先确认该基因在 18 个之内)
│
├─ 「某个星号等位由哪些 SNP 定义」
│ └─→ 用 CPIC 的 allele_definition,但**权威定义在 PharmVar**
│
├─ 「某个人群某等位的频率是多少」
│ └─→ 用 CPIC 的 allele_frequency(387,734 条),或直接用 1000 Genomes
│
├─ 「怎么给医生写一条检验后提示」
│ └─→ ✅ 用 CPIC 的 test_alert(2,213 条现成文本)
│
└─ 「这个患者的用药建议」
└─→ ❌ 不要用任何数据库直接回答。CPIC 是群体规则,个体决策需要医师
§10.2 与 PharmCAT 的分工(基因型判定 ↔ 表型映射)
这是最实用的一组配合:
| 环节 | 工具 | 输入 | 输出 |
|---|---|---|---|
| 1. VCF → 星号等位 | PharmCAT(依赖 PharmVar 定义) | VCF | CYP2D6 *1/*4 |
| 2. 星号等位 → 表型 | CPIC diplotype 表 |
*1/*4 |
Intermediate Metabolizer |
| 3. 表型 → 建议 | CPIC recommendation 表 |
IM + 可待因 | 「减量或换药」 |
三步的分界线很干净:PharmCAT 负责「测出来的序列是什么」,CPIC 负责「这意味着什么、该怎么办」。
一个实操提醒:PharmCAT 的输出里,星号等位的格式与 CPIC
diplotype.diplotype字段的格式不完全一致(分隔符、空格、是否需要基因名前缀)。接这两步时,字符串归一化是必做的一步,不能直接 join。
§10.3 与 DPWG 的类比(跨体系对照)
CPIC 与 DPWG(荷兰药物基因组学工作组)是两套平行的国际推荐体系。 它们的差异对本站有价值:
| 维度 | CPIC | DPWG |
|---|---|---|
| 归属 | 美国,ClinPGx 体系 | 荷兰皇家药师协会(KNMP) |
| 分级 | A/B/C/D + Strong/Moderate/Optional | 独立分级体系 |
| 覆盖面 | 132 基因 / 324 药 | 部分重叠,另有 CPIC 未覆盖的 |
| 数据格式 | 开放 REST API,JSON | 主要 PDF 与网站,机器可读性弱 |
最有价值的用法是「交叉验证」:同一对药-基因,如果 CPIC 说「减 50%」、DPWG 说「减 25%」,这个分歧本身就是重要信息——它说明证据不够强,两个专家组读了同一批文献得出了不同结论。
做数据集时,不要试图「统一」两套体系。 正确做法是保留两套结论并标注来源,让下游模型学到「这里存在不确定性」。强行合并会制造虚假的确定性。
§10.4 许可梯度对照
| 资源 | 许可 | 商用 | 传染性 |
|---|---|---|---|
| CPIC(api.cpicpgx.org) | 公有领域(自称) | ✅ | 无 |
| ClinPGx 下载包 | CC BY-SA 4.0 | ✅ | 有(衍生须同许可) |
| Rfam | CC0 | ✅ | 无 |
| RNAcentral | CC0 | ✅ | 无 |
| PharmGKB(旧) | CC BY-SA 4.0 | ✅ | 有 |
同一份数据、两个入口、两套许可,这在药物基因组学领域是个真实的坑。 从 API 拿是公有领域,从下载包拿是 CC BY-SA。如果你的产品不开源,务必用 API 入口,并保留访问记录。
§10.5 三个「不要做」
一、不要用 CPIC 训练「自动开药」模型。 它给的是「相对调整方向」,不是绝对剂量。真实处方需要体重、肝肾功能、合并用药、既往反应。CPIC 的 dosinginformation 布尔字段本身就在说「这条有没有给剂量」——大部分没有。
二、不要把 C 级药-基因对当作「无效关联」删掉。 C 级(284 对,44.7%)的意思是「证据不足以支持常规检测」,不是「没关联」。删掉这 284 对,你会丢掉一半的数据,且丢掉的是「边界情况」——而边界情况恰恰是模型最容易出错的地方。
三、不要用 diplotype 表的准确率来宣传模型性能。 这张表只列「需要区分的基因型」,大部分新组合会落在已知表型类别里,任何模型在这里都能拿到很高的准确率。要展示能力,请用「留一基因」交叉验证。
§10.6 一句话总结
CPIC 不是「药物基因组学数据库」,是「已经把证据嚼碎、定级、写成祈使句的那一层」——它的价值不在于数据量(112,820 条双倍型在基因组学里很小),而在于它是唯一一个敢替临床做判断的公开资源。
用它的时候记住三件事:635 对里只有 136 对真给建议;132 个基因里只有 22 个能细到等位;2,115 条推荐里有一半是「可选」。
附录 A:本篇数字速查
| 数字 | 值 | 来源 |
|---|---|---|
| 基因 | 132 | gene 表 count |
| 药物 | 324 | drug 表 count |
| 指南 | 29 | guideline 表 count |
| 药-基因对 | 635 | pair 表 count |
| 等位基因 | 1,378 | allele 表 count |
| 等位基因定义 | 1,354 | allele_definition 表 count |
| 双倍型 | 112,820 | diplotype 表 count |
| 用药推荐 | 2,115 | recommendation 表 count |
| 检验警示 | 2,213 | test_alert 表 count |
| 支撑文献 | 1,155 | publication 表 count |
| 人群样本描述 | 3,917 | population 表 count |
| 等位基因频率 | 387,734 | allele_frequency 表 count |
| 变更日志 | 907 | change_log 表 count |
| 表型字典 | 101 | gene_result 表 count |
| A 级药-基因对 | 96(15.1%) | pair.cpiclevel 统计 |
| 用于推荐的对 | 136(21.4%) | pair.usedforrecommendation |
| 已撤回的对 | 61(9.6%) | pair.removed = true |
| 有等位基因的基因 | 22(16.7%) | allele 表去重 |
| 有双倍型的基因 | 18(13.6%) | diplotype 表去重 |
| 有流程图的药物 | 98(30.2%) | drug.flowchart 非空 |
| Strong 推荐 | 591(27.9%) | recommendation.classification |
| Moderate 推荐 | 357(16.9%) | 同上 |
| Optional 推荐 | 1,047(49.5%) | 同上 |
| No Recommendation | 108(5.1%) | 同上 |
| n/a 推荐 | 12(0.6%) | 同上 |
| A 级对涉及药物 | 78 | pair 中 A 级去重 drugid |
| CYP2D6 占对数 | 81(12.8%) | pair 按基因统计 |
| 有 API 端点 | 34(+4 个 rpc) | OpenAPI 规范 |
| DAIMS 得分 | 18.0 / 24 = 75.0% | §7.6 |
附录 B:五个可复制的查询
一、统计任意表的行数(不下载数据)
curl -s -I "https://api.cpicpgx.org/v1/diplotype" \
-H "Prefer: count=exact" -H "Range: 0-0" \
| grep -i content-range
# → content-range: 0-0/112820
二、拿「真正有推荐」的药-基因对
curl -s "https://api.cpicpgx.org/v1/pair?usedforrecommendation=eq.true&removed=eq.false&select=genesymbol,drugid,cpiclevel,pgxtesting&limit=200"
三、拿某基因的全部双倍型映射
curl -s "https://api.cpicpgx.org/v1/diplotype?genesymbol=eq.CYP2D6&select=genesymbol,diplotype,generesult,totalactivityscore&limit=5000" \
| jq '[.[] | select(.totalactivityscore != "n/a")] | length'
四、拿推荐的连接视图(省掉 join)
curl -s "https://api.cpicpgx.org/v1/recommendation_view?limit=5" | jq '.'
五、拿某个药的检验后警示文本
# RxNorm:704 = 阿米替林
curl -s "https://api.cpicpgx.org/v1/test_alert?drugid=eq.RxNorm:704&select=genes,cdscontext,alerttext" \
| jq -r '.[] | .alerttext[]' | head -5
五个查询有一个共同点:都用
Prefer: count=exact或select=或过滤条件来控制返回体量。 CPIC 的大表(112,820 / 387,734 行)不能无脑GET——实测全量一次拉取 7 分钟不返回。按维度切、按需取列,是这个 API 的正确用法。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- rnacentral — 共享标签:基因组学与多组学 / 医学问答与基准
- rfam — 共享标签:基因组学与多组学 / 医学问答与基准
- ehrshot — 共享标签:电子健康记录 / 医学问答与基准
- all-of-us-nih-legacy — 共享标签:基因组学与多组学 / 电子健康记录
- ehrxqa — 共享标签:电子健康记录 / 医学问答与基准
- mimic-iv-ext-cardiac-disease — 共享标签:电子健康记录 / 医学问答与基准
- cliniq — 共享标签:电子健康记录 / 医学问答与基准
- radnli-report-inference — 共享标签:电子健康记录 / 医学问答与基准
- uk-biobank — 共享标签:基因组学与多组学 / 电子健康记录
- finngen — 共享标签:基因组学与多组学 / 电子健康记录
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

