信息速览
心脏安全性评价里有一个被用了三十年的指标:心率校正后的 QT 间期。它的问题不是不准,而是太笼统——整条心室复极被压成一个数,药物到底改动了复极的哪一段,这个数看不出来。于是出现了一种长期困扰监管与研发的错判:某些药确实延长了 QT,心血管风险却很低;另一些药延长幅度不大,反而真出事。
二〇一六年,美国 FDA 的一支团队在《Clinical Pharmacology & Therapeutics》上报了一项临床试验,用的办法是把复极拆开看。hERG 钾通道阻滞剂拉长复极,迟钠电流阻滞剂和钙电流阻滞剂各自作用于复极的不同时段,把三类药按不同组合给同一批人,就能看出 QT 的改变落在哪一段。这个思路后来成了药物心脏安全评价从单一 QT 转向分段指标的关键证据。
随论文一起公开的,就是这份临床试验的完整心电记录:22 名 18 至 35 岁健康男女,按随机双盲五期交叉方案给药,十四个预设时点各抽三份十秒十二导联片段,合计四千二百余段,附中位搏与界标注释,以 ODC-BY 1.0 开放。它是一份从设计到标注都为「机制对照」服务的数据,不是一份普通的心电图库。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | ECG Effects of Dofetilide, Moxifloxacin, Dofetilide+Mexiletine, Dofetilide+Lidocaine and Moxifloxacin+Diltiazem |
| 简称 | ECGDMMLD(字母取自五个给药组的药名首字母) |
| 发布方 | PhysioNet,由美国 FDA 研究团队主导 |
| 首次上线 | 2016 年 9 月 15 日,版本 1.0.0 |
| 受试者 | 22 名健康男女,18 至 35 岁 |
| 试验设计 | 随机、双盲、五期交叉,期间隔一周 |
| 给药组 | 多非利特单用;美西律加减;利多卡因加减;莫西沙星加减地尔硫卓;安慰剂 |
| 记录设备 | Mortara Surveyor 连续十二导联 |
| 采集参数 | 500 Hz,幅度分辨率 2.5 微伏 |
| 发布采样率 | 1000 Hz(片段上采样后) |
| 时点数 | 14 个(给药前 −0.5 小时加给药后 13 个) |
| 每时点片段 | 3 份,各 10 秒 |
| 原始片段数 | 四千二百一十一 |
| 标注 | 中位搏半自动界标(P、QRS、T、次 T 波) |
| 格式 | MIT 格式(.dat 加 .hea)与 .atr 注释 |
| 配套表 | SCR-003 临床与测量 CSV,另附字段说明 |
| 许可 | ODC-BY 1.0,无需注册 |
| DOI | 10.13026/C2D016 |
| 注册号 | ClinicalTrials.gov NCT02308748 |
§1 它要解决的具体麻烦
1.1 药物心脏安全评价卡在哪:把一个指标当成了全部
二十世纪末到二十一世纪初,几种上市后被发现引发尖端扭转型室速的药物被陆续撤市,此后几乎所有新药在研发早期都要做一项检查:会不会延长 QT 间期。这条规则救过很多人,也误伤过很多药。原因很简单,QT 间期量的是整条心室复极——从 QRS 结束到 T 波结束,所有离子通道、所有心室壁层面的改变,都被折叠进同一个数。
重极化的时间过程其实分成至少两段:心肌细胞动作电位的平台期主要由 L 型钙电流与迟钠电流维持,而晚期复极由钾电流主导。hERG 阻滞让晚期复极延长,心电图上的表现是 T 波后半段被拉长;迟钠电流阻滞让平台期缩短,表现是 T 波峰值提前。两者都会改变 QT,但方向与临床含义完全不同。把这两种改变压成一个 QT 数,就等于把两类机制混为一谈。
这篇论文提出的做法很直接:既然 QT 太粗,就换成能分开的描述量。QRS 结束到 T 波峰值这一段(J-Tpeak)主要反映平台期,T 波峰值到 T 波结束这一段(Tpeak-Tend)主要反映晚期复极。如果两个药一起给,一个拉长 Tpeak-Tend,另一个缩短 J-Tpeak,两者的效应在 QRS 结束到 T 波结束这个总长度上部分相互抵消,只测 QT 就会低估第一类药的作用。
1.2 三条常见的错误期待
第一条,期待它是一份大规模人群心电样本。 它只有 22 个人。这个数字对横断面研究来说太小,但对五期交叉设计来说不算小——每个人在五个不同的药物状态下被反复观察,有效比较次数远高于受试者人数。拿它算患病率、算人群 QT 分布,方向从一开始就错了。
第二条,期待它是一份普通的心电分类数据。 库里没有诊断标签,也没有心律失常类别。它的标签是给药期、时点、药物名,以及心搏间期与形态测量。任务是「在这种药物状态下,复极的哪一段被改变了」,不是「这张图是正常还是异常」。
第三条,期待它的采样率能补回原始精度。 官方页面写采集 500 Hz、幅度分辨率 2.5 微伏,发布文件却是 1000 Hz。上采样只改变数据的点数,不改变有效带宽。把它当成 1000 Hz 采集的高分辨率数据来讨论高频成分,会得到看似精细、实则无意义的结果。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 验证复极分段指标能否分开两类药物机制 | 同一批人身上四个药组加安慰剂的对照 | 够,这正是它的设计目标 |
| 验证 QT 校正公式在心率变化下的稳定性 | 每期十四个时点,覆盖给药后 24 小时的节律变化 | 够,时点密度足以画出时间曲线 |
| 训练或调试自动界标检测算法 | 中位搏上的半自动界标,每条五个点 | 有条件够,标签是半自动的,需自建验证集 |
| 研究药物对 P 波、PR 间期的即时影响 | 界标里含 P 波起点,逐条表里有间期测量 | 够,但只能看十秒静息片段 |
| 估计某种药在人群中的发生率 | 无患者、无随访、无转归 | 不够,结构上做不到 |
| 研究短暂或间歇出现的心律失常 | 每时点只留三份质量最优片段 | 不够,择优抽取把异常段筛掉了 |
| 研究真实门诊心电图中的噪声与伪迹 | 片段经软件挑选,噪声被主动排除 | 不适用,方向相反 |
| 复现论文里的剂量反应分析 | 有给药期与时点,但剂量细节需回原文 | 部分够,需配合论文方法节 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你手上有一个新的 QT 校正公式,想证明它比 Bazett 稳 | 每期十四个时点的心率跨度大,同一人多状态可比 | 用同一条记录的 J-Tpeak 与 Tpeak-Tend 作为参照,先确认公式没有把机制差异抹平 |
| 你在做自动复极界标算法,缺带真值的开发集 | 四千余条中位搏,每条五个界标,量足够做迭代 | 先按 §4.2 的案例抽查一批界标,把算法口径与官方标定口径对齐 |
| 你要向团队解释「为什么只看 QT 会漏掉迟钠电流阻滞」 | 美西律、利多卡因与多非利特的组合恰好是这一幕的对照 | 取同一受试者两个给药期的中位搏,画 J-Tpeak 与 Tpeak-Tend 分开的对比图 |
| 你在做药物心脏安全的监管科学教学 | 五期交叉设计与分段指标是现成的教材案例 | 用 §9.2 的最短流程跑通一条记录,再扩展到整期 |
| 你要训练一个十二导联基础模型,缺带药物背景的标注数据 | 提供药物状态与时间轴两个维度的标签 | 把它当增广或对照集,不要把 22 人当作预训练规模 |
| 你在比较多个药物试验的一致性与差异 | 与 ECGRDVQ 同期同设计,可直接做方法学比对 | 对齐时间轴与指标定义,再把两库的结论并列陈述 |
1.5 一句话判断
它的价值不在人数,而在「同一个人换四种药」这件事本身:把受试者之间的差异压到最低,让药物之间的差异浮出来。
1.6 不适合谁:四条边界
不适合需要人群统计的人。 22 名 18 至 35 岁健康志愿者不是任何意义上的人群样本。想要报告某类人群的 QT 分布、性别差异、年龄趋势,这份数据一个都给不出。
不适合做临床风险预测的人。 没有随访、没有转归、没有心律失常事件。它测量的是一条波形在药物作用下的形变,不测量后续会不会出事,两者之间还隔着很长的推理链。
不适合研究阵发性或短暂现象的人。 每期虽然连续记录了整段时间,但入库的只是十四个时点各三份质量最优片段。非持续性事件如果没有恰好落在这些片段里,库里就看不见。
不适合把原始采集精度当作发布精度的人。 1000 Hz 的发布文件背后是 500 Hz 的采集。凡是涉及高频细节的分析——比如晚电位、碎裂 QRS 的精细形态——都要先想想这层差别。
§2 数据构成与规格
2.1 两个目录加一张表:三层结构
数据结构只有三层,但每层承担的任务完全不同。raw 是波形本体,medians 是由波形导出的代表搏动,根目录的 CSV 是把波形和试验背景连起来的索引。三层之间靠编号对齐,不靠目录名对齐,这一点决定了取数时的第一件事必须是读表而不是读目录。
raw 下的子目录有两种命名口径:一种是受试者编号,另一种是随机化编号 RANDID。两者都指同一个人,但来源不同——受试者编号是入组时分配的,RANDID 是随机化系统分配的。官方页面明确说 raw 子目录「按受试者编号或随机化编号命名」,也就是说同一批文件在不同情境下可能表现出两种目录名。取数时应以 CSV 的 RANDID 列为准,再用目录名做交叉核对。
| 层级 | 位置 | 内容 | 单位 | 用途 |
|---|---|---|---|---|
| 根目录 | 无 | 临床与测量 CSV、字段说明 | 一行一条 | 索引与元数据 |
| 一级目录 | raw/ |
原始抽取片段 | 一条一个文件对 | 波形分析主入口 |
| 二级目录 | raw/<编号>/ |
按受试者或 RANDID 分目录 | 同一人共存 | 按人组织 |
| 文件 | .dat 加 .hea |
MIT 格式信号与头文件 | 10 秒 | 实际波形 |
| 一级目录 | medians/ |
中位搏 | 一条一个文件对 | 复极测量主入口 |
| 文件 | .atr |
界标注释 | 五个界标 | 测量真值 |
| 根目录 | SCR-003.Clinical.Data.csv |
逐条心电的表 | 一条一行 | 关联给药期与测量 |
| 根目录 | SCR-003.Clinical.Data.Description.txt |
列说明 | 纯文本 | 理解字段含义 |
2.2 字段与注释的完整字典
官方把字段说明单独存成文本文件,这一点很关键:CSV 的列名本身不足以推断含义,必须对照说明文件读。表里的列大致分四类:身份列、试验设计列、间期测量列、形态测量列。下面这张表按类别整理,其中「官方正文未逐项解释」的,是方法节里没有定义、只能从列名与论文方法节反推的部分。
| 字段或注释项 | 所在位置 | 取值形态 | 含义 |
|---|---|---|---|
| 受试者编号 | raw/ 目录名 |
数字串 | 入组编号 |
| 随机化编号 RANDID | raw/ 目录名或 CSV 列 |
数字串 | 随机化系统编号,官方指定用它做关联 |
| 记录名 | .hea 首行首字段 |
与文件名一致 | 片段标识 |
| 通道数 | .hea 首行第 2 字段 |
12 | 标准十二导联 |
| 采样率 | .hea 首行第 3 字段 |
1000 | Hz,上采样后 |
| 采样点数 | .hea 首行第 4 字段 |
10000 | 十秒 |
| 存储格式 | 信号行 | 16 | 16 位整数 |
| 导联名 | 信号行末字段 | I、II、III、aVR 等 | 十二导联标准命名 |
| 给药期 | CSV 列 | 1 至 5 | 第几期 |
| 时点 | CSV 列 | 14 个编号之一 | 相对给药的时间 |
| 药物 | CSV 列 | 药名或安慰剂 | 该期所用药物 |
| 人口学 | CSV 列 | 年龄、性别等 | 受试者背景 |
| 心搏间期 | CSV 列 | 测量值 | 官方正文未逐项解释各列定义 |
| 形态测量 | CSV 列 | 测量值 | 官方正文未逐项解释各列定义 |
| P 波起点 | .atr 注释 |
时间点 | 心房除极开始 |
| QRS 起点 | .atr 注释 |
时间点 | 心室除极开始 |
| QRS 终点 | .atr 注释 |
时间点 | 心室除极结束,即 J 点 |
| T 波峰 | .atr 注释 |
时间点 | 主 T 波峰值 |
| 次 T 波峰 | .atr 注释 |
时间点,可缺 | 双峰 T 波时存在 |
| T 波终点 | .atr 注释 |
时间点 | 复极结束 |
| 注释角色 | .atr 文件 |
单个注释符 | 界标类型由注释符区分 |
2.3 一段记录的完整解剖
以某一位受试者某一给药期某个时点的第一份片段为例。下载完成后,头文件的开头是这样的(只列前三条导联,其余九条格式相同):
1001_1_5_1 12 1000 10000
1001_1_5_1.dat 16 1000.0(0)/mV 16 0 200 0 I
1001_1_5_1.dat 16 1000.0(0)/mV 16 0 200 0 II
1001_1_5_1.dat 16 1000.0(0)/mV 16 0 200 0 III
第一行给出记录名、12 个通道、1000 Hz、10000 个采样点。10000 除以 1000 正好是十秒,与官方描述的片段长度吻合。后面每行是一条导联:共用同一个 .dat,16 位存储,增益 1000,单位毫伏,导联名按 I、II、III 的顺序排列。记录名里的分段在不同受试者上未必完全一致,取数时应以 CSV 与目录为准,不要假定文件名各段的位置固定。
对应的中位搏记录则多了一个 .atr:
#-- 中位搏为单导联式的向量合成导联
#-- 界标依次为 P 起点、QRS 起点、QRS 终点、T 峰、T 终点
注释里没有坐标信息,因为界标的位置直接由注释文件的采样序号给出。读取方式:
import wfdb
#-- 原始片段:12 导联 10 秒
raw = wfdb.rdrecord("raw/1001/1001_1_5_1", physical=True)
print(raw.n_sig, raw.fs, raw.sig_len)
#-- 12 1000 10000
#-- 中位搏与界标
med = wfdb.rdrecord("medians/1001_1_5_1", physical=True)
ann = wfdb.rdann("medians/1001_1_5_1", "atr")
print(med.n_sig, med.sig_len)
print(list(zip(ann.sample, ann.symbol)))
中位搏的长度与原始片段不同,它只覆盖一个心搏周期。因此把中位搏的界标序号直接映射回原始片段的采样点是错误的——两者不在同一时间轴上。要做逐段验证,必须自己在中位搏上重算时间,或者回原始片段重新定位。
2.4 五个给药期与十四个时点构成的网格
数据的主体结构是一张二维网格:纵轴是五个给药期,横轴是十四个时点。每个格子下有三份重复片段。这张表把格子数算清楚,是因为它决定了「一条完整随访链」到底有多少条记录。
| 剂量期 | 时间点 | 距给药 | 抽取份数 | 备注 |
|---|---|---|---|---|
| 给药前 | 1 | −0.5 小时 | 3 | 基线 |
| 给药后 | 2 | 1.5 小时 | 3 | 早期 |
| 给药后 | 3 | 2 小时 | 3 | 早期 |
| 给药后 | 4 | 2.5 小时 | 3 | 早期 |
| 给药后 | 5 | 3 小时 | 3 | 早期 |
| 给药后 | 6 | 6.5 小时 | 3 | 中期 |
| 给药后 | 7 | 7 小时 | 3 | 中期 |
| 给药后 | 8 | 7.5 小时 | 3 | 中期 |
| 给药后 | 9 | 8 小时 | 3 | 中期 |
| 给药后 | 10 | 12 小时 | 3 | 晚期 |
| 给药后 | 11 | 12.5 小时 | 3 | 晚期 |
| 给药后 | 12 | 13 小时 | 3 | 晚期 |
| 给药后 | 13 | 13.5 小时 | 3 | 晚期 |
| 给药后 | 14 | 24 小时 | 3 | 次日 |
十四个时点的分布不是均匀的。给药后前四个时点集中在 1.5 至 3 小时,紧接着四个集中在 6.5 至 8 小时,再四个集中在 12 至 13.5 小时,最后一个是 24 小时。官方解释这个安排的理由:三个维持剂量分别在上午、下午、晚上给药,每段的起止时刻是血药浓度的峰值区,因此重点采样;中途的 30 分钟与 120 分钟采血点则另外取片段。三个密度带正好对应三个给药高峰。
2.5 与 ECGRDVQ 的字段差异
库内另有一条同期发布的姊妹库 ECGRDVQ,两者的结构几乎可以逐列对照。它们之间的差异,正好说明了「同为 FDA 五期交叉试验」并不等于「同一份数据」。
| 对比项 | ECGDMMLD | ECGRDVQ |
|---|---|---|
| 药物组合 | 多非利特、美西律、利多卡因、莫西沙星、地尔硫卓 | 雷诺嗪、多非利特、维拉帕米、奎尼丁 |
| 设计思想 | 三类电流阻滞的叠加对照 | 四种作用机制各异的药物并列 |
| 时点数 | 14 | 16 |
| 原始片段 | 四千二百余段 | 五千二百余段 |
| 采集参数 | 500 Hz,2.5 微伏 | 500 Hz,2.5 微伏 |
| 发布采样率 | 1000 Hz | 1000 Hz |
| 标注 | 中位搏界标 | 中位搏界标 |
| 发布日 | 2016 年 9 月 15 日 | 2016 年 7 月 26 日 |
| 配套表 | SCR-003 | SCR-002 |
| 许可 | ODC-BY 1.0 | ODC-BY 1.0 |
两条库的 CSV 文件名只差一个编号,这本身就是一个提醒:在 PhysioNet 上按文件下载时,脚本里若把论文名拼进路径,很容易把两张表搞混。稳妥做法是按库名分别建立下载目录,再在合并前用列名核对。
§3 定位:它测的是复极的分裂,不是心律
3.1 一个时间轴上的三段:J-Tpeak 与 Tpeak-Tend
要理解这份数据为什么值得单独建库,得先理解它的测量对象。一条心电图上的 QRS 复合波结束点被称为 J 点,从 J 点到 T 波结束的整段是 QT 间期。论文把它拆成两截:J 点到 T 波峰值,以及 T 波峰值到 T 波结束。
第一截主要反映动作电位的平台期。平台期由 L 型钙电流的内流与迟钠电流的内流共同维持,任何让这两种电流减小的药,都会让平台期缩短,心电图上的 J-Tpeak 就变短。第二截主要反映动作电位的晚期复极,由钾外流主导,hERG 阻滞让外流变慢,Tpeak-Tend 就变长。
这个拆分的直接后果是:只测 QT 时,一个同时缩短 J-Tpeak、延长 Tpeak-Tend 的药,可能看起来「QT 几乎没变」。而实际上,它把晚期复极拉长了。这就是论文要演示的错判场景。
| 分段 | 时间范围 | 主要离子机制 | 该类药的作用方向 |
|---|---|---|---|
| QRS | 除极 | 钠内流 | 一般不受本次涉及的药影响 |
| J-Tpeak | 平台期 | 钙内流加迟钠内流 | 迟钠或钙阻滞使其缩短 |
| Tpeak-Tend | 晚期复极 | 钾外流(含 hERG) | hERG 阻滞使其延长 |
| QT | J 点到 T 波结束 | 以上两段之和 | 两类效应可能相互抵消 |
3.2 五期交叉设计的妙处:让每个人当自己的对照
随机交叉设计在这类研究里的意义,比在普通临床试验里更大。复极时长受个体差异影响极强——同年龄同性别的人,基线 QT 可以差几十毫秒。如果采用平行分组,药与药之间几十毫秒的差异很容易被个体差异淹没。交叉设计让每个受试者在五个不同状态下被反复测量,比较发生在同一个人体内,个体间方差被直接去掉。
代价是残留效应与顺序效应的风险,因此官方说明两个给药期之间间隔一周,让前一种药完全代谢。这个间隔长度不是随意定的:多非利特的半衰期长,一周是让它在体内清空所需的保守估计。
| 设计要素 | 官方做法 | 对分析的影响 |
|---|---|---|
| 随机化 | 随机双盲 | 给药顺序不会系统性偏向某一组 |
| 交叉 | 五期,同一人全做 | 个体内比较,方差更小 |
| 洗脱 | 期间隔一周 | 前一期的药效基本清除 |
| 给药次数 | 每期一日内三次 | 时点密度围绕三个峰值 |
| 体位 | 仰卧静息十分钟后抽取 | 体位与活动对复极的影响被压住 |
| 采血 | 每期十二次 | 支持暴露-反应分析 |
3.3 为什么药名要写进库名
五个给药组不是随意凑的,每一个都有明确的功能位。多非利特是强 hERG 阻滞剂,作为「已知会延长 QT 的阳性对照」;莫西沙星是临床上另一类会被关注 QT 的抗菌药,作为第二种阳性对照;美西律与利多卡因都是迟钠电流阻滞剂,分别口服与静脉给药,用来检验「加一个迟钠阻滞能不能把 QT 拉回来」;地尔硫卓是钙通道阻滞剂,用来检验钙电流这一路的作用。
这四个字母加地尔硫卓的首字母拼成 DMMLD,正是这份数据的设计说明。库名不是随意缩写,而是把实验方案写在了名字里。也正因为如此,任何把 DMML 理解成「数据挖掘」或「机器学习」的猜测,都会把使用方向带偏。
| 药物 | 主要作用靶点 | 给药途径 | 在试验中的角色 |
|---|---|---|---|
| 多非利特 | hERG 钾通道 | 口服 | 阳性对照,拉长晚期复极 |
| 莫西沙星 | hERG 钾通道 | 静脉 | 第二种阳性对照 |
| 美西律 | 迟钠电流 | 口服 | 检验迟钠阻滞能否抵消 hQT |
| 利多卡因 | 迟钠电流 | 静脉 | 同上,用药途径不同 |
| 地尔硫卓 | L 型钙通道 | 静脉 | 检验钙电流这一路 |
| 安慰剂 | 无 | 当期不给活性药 | 基线 |
§4 质量与特色:标注是怎么做出来的
4.1 三份片段怎么挑:择优抽取的利与弊
原始连续记录是几十小时量级,入库的却是每时点三份十秒片段。这个转换由 Antares 软件完成,选择标准写得很清楚:心率稳定、信号质量最佳。三点需要注意。
第一,抽取发生在每次采血之前。官方说在这十四时点采血前抽取片段,因为采血时受试者必须保持静卧,体位一致,干扰最小。这让每个时点的片段在采集条件上高度可比,也意味着任何与采血相关的短暂变化都不会被记录。
第二,「三份」是为了一次内重复。同一时点取三份,是为了在测量时取中位或做一致性检验。它不等于三个独立样本,把它们当独立样本会高估有效样本量。
第三,择优意味着噪声不是随机的。任何需要研究实际噪声分布的应用,都不能用这份数据——它把噪声主动筛掉了。
| 处理环节 | 官方做法 | 得到的能力 | 失去的信息 |
|---|---|---|---|
| 连续记录 | 500 Hz 十二导联 | 全程覆盖 | 无 |
| 时点选择 | 十四个预设时点 | 时间轴规整可比 | 时点之间的过渡 |
| 择优抽取 | 心率稳、质量最佳 | 片段干净、可测 | 差质量片段与噪声 |
| 三份重复 | 每时点 3 份 | 一次内一致性 | 三份以外的变异 |
| 上采样 | 500 Hz 到 1000 Hz | 采样点加密 | 有效带宽不变 |
| 中位搏 | 逐导联取中位 | 单搏代表,抗噪 | 逐搏变异 |
4.2 案例:一张美西律给药期的中位搏
这里用一个具体场景把数据处理的全过程走一遍:随机化编号 1001 的一位受试者,在第 2 期某时点的记录。这个案例会在 §5、§7 与 §9 中反复出现。
这位受试者在第 2 期接受的是「美西律加或不加多非利特」这一组。要看清迟钠阻滞的作用,得把同一受试者第 1 期(多非利特单用)与第 2 期的中位搏并排看。具体做法分四步:先从 CSV 里按 RANDID 与期号筛出记录名;再从 medians 目录读出两条中位搏与它们的 .atr;接着在两条中位搏上分别算出 J 点到 T 波峰值、T 波峰值到 T 波结束这两段时长;最后把差值画出来。
这个流程的关键在于「同一人、同一时点、不同期」。如果拿来比较的是两个人,个体差异会直接盖过药物效应。如果比较的是同一期的不同时点,药物浓度差异会混进来。只有同一人同一时点的期与期对比,尽量把两个变量都按住。
import wfdb
import pandas as pd
df = pd.read_csv("SCR-003.Clinical.Data.csv", encoding="utf-8-sig")
mask = df["RANDID"].astype(str).eq("1001") & df["period"].isin([1, 2])
sel = df.loc[mask].copy()
print(sel[["period", "tp", "drug"]].head(12))
#-- 期号 1 与 2,药物列显示该期方案
列名以实际下载的 CSV 为准,官方把列说明放在单独的文本文件里。如果表里的列名与上面的写法对不上,先读说明文件,不要凭猜测改列。
4.3 半自动界标的边界:它为什么不是金标准
官方对标注的措辞是「半自动」:先把中位搏算出来,再在向量合成导联上跑自动算法,由算法给出五个界标。这里没有说明是否经过人工逐条复核。
这个细节在使用时很关键。半自动标注的一致性问题在于:算法在正常形态上很稳,在双峰 T 波、平低 T 波、U 波融合这些情形上容易出现系统性偏移。而这份数据的设计恰好会诱发这些形态——药物本身就会改变 T 波形状。
| 界标 | 定义依据 | 稳定情形 | 易偏情形 |
|---|---|---|---|
| P 波起点 | 向量合成导联 | 窦性心律清晰 | P 波低平 |
| QRS 起点 | 同上 | 窄 QRS | 起始部有顿挫 |
| QRS 终点 | 同上 | J 点明确 | J 点与 S 波尾融合 |
| T 波峰 | 同上 | 单峰 T 波 | 双峰时取哪一个 |
| 次 T 波峰 | 同上,可缺 | 双峰清晰 | 双峰难分 |
| T 波终点 | 同上 | 回到基线 | 与 U 波融合 |
4.4 中位搏:把十秒压成一个搏动
中位搏不是随手挑一个好看的搏动,而是逐样本同步后取中位数。同步以一个导联的 QRS 为锚点,把十秒内所有心搏对齐,再对每个采样位置取中位数。官方还加了一条排除规则:非窦性搏按互相关系数与 RR 间期历史剔除。
这一步的价值是抗噪——单个搏动上的伪迹在取中位时被摊薄。代价是逐搏信息全部丢失。任何与「某一次搏动特别不一样」相关的问题,在中位搏上都问不出来。
| 维度 | 原始十秒片段 | 中位搏 |
|---|---|---|
| 导联数 | 12 | 单条合成导联为主 |
| 时长 | 10 秒 | 约一个心搏周期 |
| 心搏数 | 十秒内全部 | 合并为一个代表 |
| 噪声敏感性 | 高 | 低 |
| 逐搏变异 | 保留 | 丢失 |
| 界标 | 需自行标注 | 已给出 |
| 适合任务 | 节律、逐搏、逐导联形态 | 复极测量、批量化对比 |
4.5 为什么这份数据的「质量」体现在设计而非数量
评估一份数据集,常见的思路是看样本量、看标注密度、看覆盖范围。这份数据在这三项上都不突出:22 人,每时点三份,五个给药组。它的质量体现在另一个维度——对照的严密性。
随机化、双盲、交叉、期间隔一周、仰卧静息十分钟后抽取、每期十二次采血、十四个时点覆盖 24 小时。这些条件共同保证了:当观测到药物之间某个指标出现差异时,差异更可能来自药物本身,而不是体位、时间、个体或操作者。这类质量用数字很难描述,但它决定了数据的可用上限。
| 质量维度 | 本库表现 | 说明 |
|---|---|---|
| 样本量 | 低 | 22 人 |
| 标注密度 | 中 | 中位搏五个界标 |
| 覆盖范围 | 窄 | 健康年轻人,五种给药方案 |
| 对照严密性 | 高 | 随机双盲交叉,条件固定 |
| 时间分辨率 | 中 | 十四个时点,24 小时覆盖 |
| 波形质量 | 高 | 择优抽取,噪声被筛掉 |
| 可重复性 | 高 | 固定设备、固定软件、固定流程 |
§5 怎么拿到:从编号到一条可分析记录
5.1 访问:许可开放但存在地区限制
官方标注的访问策略是「只要遵守指定许可的条款,任何人都可以访问文件」。许可为 ODC-BY 1.0。不过,本次核对时官方页面文件区显示的是地区不可用的提示,说明实际下载还受 PhysioNet 的地区访问策略约束。
这带来一个实践上的建议:先确认自己所在的网络环境能否直接取到文件,再决定后续技术路线。若只是要做教学演示,可以从论文的方法节与官方页面说明入手;若要做波形分析,则必须解决下载问题。
| 访问项 | 状态 | 说明 |
|---|---|---|
| 是否需要注册 | 否 | 官方声明无需注册即可访问 |
| 许可类型 | ODC-BY 1.0 | 允许商用,须署名 |
| 地区限制 | 存在 | 本次核对时文件区显示不可用 |
| 整包下载入口 | 有 | get-zip/1.0.0/ 路径 |
| 逐文件下载 | 有 | files/ecgdmmld/1.0.0/ 目录 |
| 文件清单 | 存在 | RECORDS 与校验和文件 |
5.2 体量与格式:先算清楚再下载
官方页面没有直接给出整包体积,因此无法在不下载的前提下给出确切数字。可以确定的是:每段十秒、十二导联、16 位、1000 Hz,按 MIT 格式存储时单条信号文件的长度就是这个乘法结果。这个算式能帮你估算体量,但不能替代官方数字。
| 参数 | 值 | 来源 |
|---|---|---|
| 单段时长 | 10 秒 | 官方正文 |
| 采样率 | 1000 Hz | 官方正文 |
| 通道数 | 12 | 官方正文 |
| 位深 | 16 位 | MIT 格式惯例 |
| 单段采样点 | 10000 | 10 × 1000 |
| 单段理论字节 | 240000 | 10000 × 12 × 2 |
| 原始片段数 | 四千二百一十一 | 官方正文 |
| 整包体积 | 官方未标注 | 未核实 |
5.3 用 wfdb 读一条记录
import wfdb
import numpy as np
rec = wfdb.rdrecord("raw/1001/1001_1_5_1", physical=True)
print(f"{rec.n_sig} 导联 / {rec.fs} Hz / {rec.sig_len} 点")
#-- 12 导联 / 1000 Hz / 10000 点
sig = rec.p_signal
print(sig.shape, rec.units[0])
#-- (10000, 12) mV
#-- 取 II 导联做一次简单峰值定位,仅用于确认读取正常
lead2 = sig[:, 1]
thr = np.percentile(np.abs(lead2), 99)
peaks = np.where(np.abs(lead2) > thr)[0]
print(len(peaks), "个超阈值点")
这段代码的重点是确认读取链路通畅。真正的复极测量必须用中位搏,因为原始片段的量化噪声足以让 T 波终点的判定来回跳动几百毫秒。
5.4 读中位搏与界标
import wfdb
med = wfdb.rdrecord("medians/1001_1_5_1", physical=True)
ann = wfdb.rdann("medians/1001_1_5_1", "atr")
fs = med.fs
x = med.p_signal[:, 0]
for s, sym in zip(ann.sample, ann.symbol):
print(f"{sym} @ {s} 点 = {s / fs * 1000:.1f} 毫秒")
中位搏通常按合成导联给出。若库内同一记录存在多条导联的中位搏文件,取数时要先确认自己读的是哪一条。界标序号是相对于中位搏起点的采样序号,不能与原始片段的序号混用。
5.5 把一条记录放回它的试验背景里
import wfdb
import pandas as pd
clin = pd.read_csv("SCR-003.Clinical.Data.csv", encoding="utf-8-sig")
row = clin.loc[clin["RANDID"].astype(str).eq("1001")].head(1).iloc[0]
print(row[["RANDID"]].to_dict())
ann = wfdb.rdann("medians/1001_1_5_1", "atr")
jm = [s for s, y in zip(ann.sample, ann.symbol)]
print("界标点数:", len(jm))
#-- 五个界标,双峰 T 波时六个
这一步是整条取数链路里最容易被跳过、却也最影响结论的一环。脱离给药期与时点的波形,只能说明「这张图长什么样」,说明不了「这个形状是哪个药造成的」。
5.6 批量遍历:把目录当索引
import os
import wfdb
root = "medians"
rows = []
for sub in sorted(os.listdir(root)):
p = os.path.join(root, sub)
if not os.path.isdir(p):
continue
for fn in sorted(os.listdir(p)):
if not fn.endswith(".hea"):
continue
stem = os.path.join(p, fn[:-4])
try:
ann = wfdb.rdann(stem, "atr")
except Exception as exc:
rows.append((stem, 0, str(exc)))
continue
rows.append((stem, len(ann.sample), "ok"))
print(len(rows), sum(1 for r in rows if r[2] == "ok"))
这段遍历的作用不是统计,而是建立一张「哪些记录可用」的清单。遇到读取失败的文件先记下来,不要跳过——失败本身可能说明某条记录缺少中位搏或注释。
§6 与库内条目的关系
6.1 关系图谱
库内与这份数据最接近的是 ECGRDVQ。两者同期、同源、同设计,研究的是同一类问题:药物如何改变复极的不同分段。差异在药物谱与规模。把它放在一起看,能看出 FDA 团队在两年间用同样的框架做了两次试验,一次验证四种不同机制的药能否被分段区分,一次验证迟钠阻滞与钙阻滞能否在 QT 上相互抵消。
第二近的是 CiPA 心电验证研究。它把同样的想法扩展到 60 名受试者、七个给药组、五千七百余段记录,是这一思路的放大版。本库规模小、结构简单,适合当开发集与方法演示;CiPA 更适合当确认集。
再往外是 QT Database 与 MIT-BIH 系列。它们提供波形边界标注的金标准,但对象是普通临床心电或标准数据库记录,没有药物背景与逐时点设计。两者解决的是不同问题:一个解决「界标标得准不准」,一个解决「药物改变了哪一段」。
| 库内条目 | 关系 | 主要差异 |
|---|---|---|
| ECGRDVQ | 同期姊妹库 | 药物谱与时点数不同,规模相近 |
| CiPA 心电验证研究 | 后续放大验证 | 60 人、七组、五千七百余段 |
| QT Database | 界标金标准来源 | 无药物背景,专注边界标注 |
| BUT QDB | 信号质量维度 | 关注能不能用,不关注复极分段 |
| MIMIC-IV-ECG | 临床真实场景 | 大规模,但无受控给药设计 |
6.2 检索路径
要在库内找到这一类资源,可以沿三条线索走。第一条是按类别标签,生理信号 加 心电信号 能覆盖绝大多数心电库,药物安全 则是把范围收窄到药物试验类的关键。第二条是按机构,PhysioNet 上由 FDA 团队主导的数据集形成一个可以整体浏览的小集合。第三条是按设计特征,凡是「五期交叉」「随机双盲」「十秒片段」同时出现,基本可以判定是同一类试验产物。
| 检索线索 | 关键词 | 预期命中 |
|---|---|---|
| 类别标签 | 生理信号、心电信号 | 全部心电库 |
| 细分标签 | 药物安全 | 药物试验类心电库 |
| 设计特征 | 五期交叉、随机双盲 | 本库与 ECGRDVQ |
| 指标特征 | J-Tpeak、Tpeak-Tend | 复极分段类研究 |
| 机构线索 | FDA、CDER、OSEL | 同源数据集集合 |
| 注册号 | NCT02308748 | 试验登记信息 |
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
在评价这份数据之前,必须先纠正一个视角上的错位:它不是为通用心电研究准备的数据集,而是一次临床试验的完整档案。 如果按「数据集评测」的尺子去量它——样本量够不够、类别均不平衡、标注覆盖全不全——几乎每一项都会显得不足。但如果按「试验证据」的尺子去量,它是一份设计严密、可追溯、可复核的原始材料。
这个错位会直接导致误判。比如把它和 MIMIC 那样的百万级临床心电库比较样本量,得出「太小不可用」的结论;或者把它和 QT Database 比较标注密度,得出「标注太稀」的结论。两种比较都成立,但都没回答它能不能用。它能不能用,取决于问题是不是「在受控给药条件下,复极的哪一段被改变了」。
7.1 五维评分
| 维度 | 评分 | 依据 |
|---|---|---|
| 可获取性 | 4 | ODC-BY 1.0,无需注册;但存在地区限制 |
| 结构清晰度 | 4 | 目录加 CSV 索引,字段有单独说明;文件名分段口径需核实 |
| 标注可靠性 | 3 | 半自动界标,无人工复核说明;中位搏压制逐搏变异 |
| 设计严密性 | 5 | 随机双盲五期交叉,条件固定,覆盖 24 小时 |
| 人群代表性 | 2 | 22 名健康年轻人,不代表患者群体 |
这里的评分不是优劣排名,而是把「能用在哪一层」写清楚。设计严密性拿到最高,是因为这份数据最不可替代的地方就在设计;人群代表性最低,是因为它本来就没打算代表谁。DAIMS 框架里,数据与模型的关联、来源可追溯与使用限制是三个独立维度,这份数据在第一项上清晰、第二项上完备、第三项上明确,因此尽管人群维度薄弱,整体仍然合格。
7.2 三类可预期的使用偏差
第一类是过度外推。 在 22 名健康志愿者身上观察到的 QT 变化,是这类药在无基础心脏病、年轻、肝肾功能正常的人身上的表现。老年患者、合并用药者、已知长 QT 者会有完全不同的反应。把这里的均值当成临床剂量决策依据,是最常见的误用。
第二类是把中位搏当逐搏。 中位搏是压缩过的代表搏动,所有逐搏特征都被平均掉了。用它评估「算法能不能在每一搏上稳定工作」,会得到明显偏高的准确率,因为输入本身已经被平滑过。
第三类是把时点当连续。 十四时点覆盖的是 24 小时中的离散时刻,不是连续轨迹。在两个时点之间画出的曲线是插值,不是观测。用药代动力学模型拟合这些点时,要清楚拟合的对象是稀疏采样。
7.3 已知的、可枚举的偏差
| 偏差 | 性质 | 影响 |
|---|---|---|
| 受试者年龄集中 | 设计选择 | 不能外推到老年与儿童 |
| 全部健康 | 设计选择 | 不能外推到患者 |
| 性别比例固定 | 设计选择 | 难以单独分析性别效应 |
| 瞬时 T 波改变 | 设计选择 | 只能看到峰值时刻的改变 |
| 片段择优抽取 | 处理步骤 | 噪声与差质量片段缺失 |
| 中位搏压缩 | 处理步骤 | 逐搏细节消失 |
| 界标半自动 | 标注方式 | 异常形态上可能系统性偏移 |
| 单中心 | 试验设计 | 设备与流程固定,跨中心可比性未知 |
7.4 外部验证矩阵
这份数据被引用的场景大致集中在四类。第一类是复极分段指标的方法学研究,用它的药物对照关系验证新指标的敏感性。第二类是 QT 校正公式的比较研究,用它在不同心率下的数据检验公式差异。第三类是自动界标算法的开发与测试。第四类是监管科学教学,用来演示为什么单一 QT 指标不够。
| 验证场景 | 数据用法 | 需注意 |
|---|---|---|
| 指标敏感性验证 | 分组对比 J-Tpeak 与 Tpeak-Tend | 需先统一界标口径 |
| QT 校正公式比较 | 用逐时点的心率与 QT 配对 | 注意时点分布不均匀 |
| 界标算法测试 | 以中位搏与 .atr 为参照 |
参照本身是半自动的 |
| 教学演示 | 用同一人的不同期对照 | 强调是机制演示而非临床结论 |
7.5 它为何能持续:因为每次谈起药物心脏安全,都要回到这张分段表
这份数据发布至今快十年,PhysioNet 上只有一个版本,没有改版、没有扩样。它能持续存在,原因不在数据本身会更新,而在于它回答的那个问题一直在:只要药物研发还在用 QT 作为筛查指标,就总有新的团队需要一份「同一个受试者、四种药、分段测量」的对照材料来检验自己的方法。这个需求不是一次性的,而是随着每一项新的复极指标出现而被重新激活一次。
§8 生态位与历史
8.1 从撤市潮到分段指标:一条二十年的事故链
这条线索的起点在上世纪九十年代末。几种非心脏类药物因为引发尖端扭转型室速被撤市之后,监管机构确立了一条规则:几乎所有新药都要在早期做 QT 检查。规则带来了安全,也带来了新的问题——大量有潜在价值但对心脏影响轻微的药,因为 QT 轻度延长而在早期被淘汰。
要让规则更聪明,就得让指标更精确。二〇〇〇年代中期以后,研究者开始尝试把 QT 拆开。J-Tpeak 与 Tpeak-Tend 这两个量并不是新的,它们在电生理文献里已经存在很久,但作为药物评价工具被系统使用,是从这一系列试验开始的。本库就是这条链上的一环:它用一套严格对照的临床试验证明,两个分段确实能被不同类型的药分开改变。
| 阶段 | 时间 | 事件 |
|---|---|---|
| 早期 | 上世纪九十年代末 | 多药因 QT 问题撤市 |
| 规则确立 | 本世纪初 | QT 检查成为新药常规 |
| 概念形成 | 本世纪前十年 | 复极分段指标被提出 |
| 临床验证 | 本世纪一零年代 | 五期交叉试验验证分段可分开 |
| 数据公开 | 2016 年 | 本库与姊妹库上线 |
| 后续扩展 | 稍后 | CiPA 计划的临床层验证 |
8.2 一个版本,十年未改
官方页面只列出一个版本 1.0.0,发布时间 2016 年 9 月 15 日。没有后续修订记录,也没有补充材料的更新说明。这在 PhysioNet 上并不罕见:一次临床试验结束后公开的档案,基本不会再变。
这对使用者是个好消息也是个约束。好的一面是数据稳定,任何引用都指向同一份文件,长期可复现。约束的一面是错误不会被修正,如果某条记录的标注有问题,十年后仍然是那样。
8.3 在 PhysioNet 药物试验类数据集里的位置
PhysioNet 上由 FDA 团队主导的药物试验类心电数据构成一个松散的小集合。它们共享相似的试验设计、相同的采集设备、相同的处理流程,因而在字段层面高度可对照。这个集合的价值不在于总量,而在于它提供了一个可以横向比较的「同工艺样本」——同一套流程连续做了几次不同药物组合的试验,使药物之间的差异不会被工艺差异混淆。
| 数据集特征 | 本库 | 同集合的一般特征 |
|---|---|---|
| 试验设计 | 五期交叉 | 多数为四至六期交叉 |
| 受试者 | 22 名健康志愿者 | 十余至六十人不等 |
| 药品种类 | 五 | 三至七种 |
| 记录规模 | 四千余段 | 数千段量级 |
| 标注形式 | 中位搏界标 | 中位搏界标 |
| 许可 | ODC-BY 1.0 | 多为 ODC-BY 1.0 |
8.4 为什么它没有变成通用基准
一个自然的疑问:既然是精心设计的对照试验,为什么没有被广泛用作药物心脏安全的通用评测基准?答案部分在数据规模,部分在任务性质。四千余段对标准化的算法竞赛来说偏少;而它的核心价值在「组间对照」而非「单条判别」,这种用法需要使用者自己构造比较实验,不像分类任务那样可以直接切分训练集与测试集。它更适合当方法学验证的参考,不适合当排行榜的赛道。
§9 使用指引
9.1 三种角色的路径
做方法学研究的人,应该从中位搏入手。先读 .atr,把界标拿出来做一致性检验,再考虑怎么改算法。做建模的人,应该从 CSV 入手,先看清给药期与时点的结构,再决定用整期序列还是单时点横截面。做教学的人,应该从同一受试者的两期对照入手,这是最能讲清分段指标价值的样本。
| 你的角色 | 建议入口 | 第一步 | 常见弯路 |
|---|---|---|---|
| 方法学研究者 | medians 与 .atr |
抽查界标一致性 | 直接拿界标当中位搏真值 |
| 建模者 | 临床 CSV | 建立期与时点的矩阵 | 忽略时点分布不均匀 |
| 教学者 | 同一人不同期 | 画两期对照图 | 用不同人的记录比较 |
| 复现论文者 | 论文方法节加 CSV | 对齐剂量与时点定义 | 按库名猜药物分组 |
9.2 一条最短的可用流程
从下载到能出一张图,最短的路径是这五步。每一步都只做一件事,做完再做下一步,避免在中间环节堆叠不确定性。
#-- 1 建目录,按库名隔离,避免与姊妹库混用
mkdir -p ecgdmmld/{raw,medians}
cd ecgdmmld
#-- 2 取字段说明,先读说明再看表
curl -fLO "https://physionet.org/files/ecgdmmld/1.0.0/SCR-003.Clinical.Data.Description.txt"
#-- 3 取临床表
curl -fLO "https://physionet.org/files/ecgdmmld/1.0.0/SCR-003.Clinical.Data.csv"
#-- 4 取一条记录头文件,确认格式
curl -fLO "https://physionet.org/files/ecgdmmld/1.0.0/RECORDS"
#-- 5 若前四步均返回 200,再走整包下载
#-- 整包入口:https://physionet.org/content/ecgdmmld/get-zip/1.0.0/
前三步不需要下载波形就能完成,且能立刻判断网络是否放行。若第 2 步返回 403,说明当前环境的访问策略不支持直接取文件,需要换网络或走镜像。
import pandas as pd
import wfdb
clin = pd.read_csv("SCR-003.Clinical.Data.csv", encoding="utf-8-sig")
print(clin.shape)
#-- 每行一段片段,列数随官方表结构
#-- 取同一受试者两期的中位搏,做一次 J-Tpeak 与 Tpeak-Tend 拆分
def repolarize(stem):
ann = wfdb.rdann(stem, "atr")
s = ann.sample
if len(s) < 5:
return None
j, tp, tend = s[2], s[3], s[-1]
return (tp - j), (tend - tp)
base = repolarize("medians/1001_1_5_1")
wrap = repolarize("medians/1001_2_5_1")
print(base, wrap)
#-- 两段时长,单位与采样率同一量纲,需据此换算毫秒
这里用「同一受试者、同一时点、不同给药期」的两条中位搏做对比,正是 §4.2 的案例在代码层面的落地。实际分析中应先确认两条记录确实属于同一时点编号,否则会把浓度差异误当成药物差异。
9.3 引用方式
官方给出的引用要求分两层。第一层是数据集本身,需引用原始论文:Johannesen 等,Late sodium current block for drug-induced long QT syndrome: Results from a prospective clinical trial,发表于 Clinical Pharmacology & Therapeutics 2016 年第 99 卷第 2 期 214 至 223 页,DOI 10.1002/cpt.205。第二层是平台,需按 PhysioNet 的推荐格式引用其对平台本身的介绍文献。数据集自身另有 DOI 10.13026/C2D016 用于定位版本。
| 引用对象 | 格式要点 | 用途 |
|---|---|---|
| 原始论文 | 作者、标题、期刊、年卷期页、DOI | 方法与结论的出处 |
| 数据集 DOI | 10.13026/C2D016 | 版本定位 |
| 平台引用 | 平台综述文献 | 说明数据托管来源 |
| 试验注册号 | NCT02308748 | 追溯试验方案 |
9.4 拿到数据后先做的三件事
第一件是核对目录名与 CSV 的一致性。官方说 raw 子目录按受试者编号或 RANDID 命名,实际下载后要确认自己这批文件用的是哪一种,并把映射关系写进脚本,而不是在后续每一步都重新判断。
第二件是确认中位搏与原始片段的对应关系。两者文件名通常一致,但中位搏的时间轴不同。若你的流程需要把界标映射回原始片段,必须自己重建时间轴,不能直接相减——§4.2 的案例在这一步最容易出错。
第三件是检查每个时点的三份片段是否齐全。官方设计是每时点三份,但实际下载或解压可能缺失。缺一份不影响测量,缺两份就要考虑是否换一个时点。
| 检查项 | 通过标准 | 失败时怎么办 |
|---|---|---|
| 目录与 CSV 对齐 | RANDID 能一一映射 | 以 CSV 为准重建索引 |
| 中位搏与片段对应 | 文件名成对存在 | 记录缺失清单,不擅自补 |
| 每时点三份齐全 | 三点都在 | 标注缺失,避免误当设计差异 |
| 导联数 | 12 | 检查头文件是否截断 |
| 采样率 | 1000 | 若为 500 说明读了未上采样的源 |
§10 AI 使用声明
| 项目 | 说明 |
|---|---|
| 数据性质 | 真实人体的临床试验心电记录,非模拟、非合成 |
| 训练使用 | 可用于模型开发与调试,须遵守 ODC-BY 1.0 署名要求 |
| 医学用途 | 不构成临床决策依据,22 人健康样本不能外推至患者 |
| 隐私 | 官方以编号替代身份,未见直接标识符 |
| 标注来源 | 界标为半自动生成,中位搏由算法导出 |
| 分布偏移 | 年轻健康人群、静息仰卧、择优片段,与现实场景差距大 |
| 责任边界 | 使用方对二次分析与结论负责 |
| 更新状态 | 单一版本 1.0.0,2016 年发布后未改版 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| DMML 是 Data Mining 或 Machine Learning | 取自多非利特、莫西沙星、美西律、利多卡因首字母 | 官方全名与库名对应 |
| 这是机器生成的心电数据 | 真实临床试验采集,真实受试者 | 官方摘要与试验设计描述 |
| 它有上万人 | 22 名健康志愿者 | 官方摘要明写 |
| 每段是连续长记录 | 每段十秒,每时点三份 | 官方文件说明 |
| 采样率 1000 Hz 就是高分辨率 | 采集 500 Hz,片段上采样到 1000 Hz | 官方方法节并列两口径 |
| 标注是人工逐条确认的金标准 | 半自动标注,无人工复核说明 | 官方用半自动一词 |
| 界标可以直接映射回原始片段 | 中位搏与片段时间轴不同 | 中位搏为压缩代表搏动 |
| 可以当 QT 分类训练集 | 无诊断标签,标签是给药期与时点 | 官方 CSV 字段构成 |
| 五个给药组是五种独立药物 | 部分组是两药叠加 | 官方全名中带加号 |
| 与 ECGRDVQ 是同一份数据 | 同日设计但药物与规模不同 | 两库官方页面 |
FAQ
Q1:DMML 这四个字母到底代表什么?
官方页面把库名写成 ECGDMMLD,全名是 ECG Effects of Dofetilide, Moxifloxacin, Dofetilide+Mexiletine, Dofetilide+Lidocaine and Moxifloxacin+Diltiazem。字母依次取自多非利特、莫西沙星、美西律、利多卡因四个药名,末尾的 D 对应地尔硫卓。官方没有单独给出缩写释义,这是按全名逐项对应的读法。
Q2:它和 ECGRDVQ 是同一次试验吗?
不是。两库同期发布、同为 FDA 团队主导、同为五期交叉、同为 22 名健康受试者,但药物组合完全不同:ECGRDVQ 研究雷诺嗪、多非利特、维拉帕米、奎尼丁;本库研究多非利特与美西律、利多卡因、莫西沙星、地尔硫卓的组合。时点数与片段数量也不同。
Q3:四千余段是怎么来的?
按官方描述,每个给药期有十四个时点,每个时点抽三份十秒片段,五个给药期合计是两百一十份每人的理论值。实际发布四千二百一十一份,说明并非所有人都完成了全部期与时点。这个差额的构成,官方页面没有逐人说明。
Q4:为什么有人说采样率是 500 Hz,有人说 1000 Hz?
两个数字描述不同环节。采集环节用 Mortara Surveyor 以 500 Hz、幅度分辨率 2.5 微伏连续记录;抽取出的十秒片段在入库前被上采样到 1000 Hz。发布文件是 1000 Hz,原始信息量仍是 500 Hz 的量级。
Q5:中位搏是什么,为什么要单独提供?
中位搏是把十秒内所有心搏按 QRS 同步后,对每个采样位置取中位数得到的代表搏动。它抗噪、便于批量测量,非窦性搏会被剔除。代价是逐搏变异被抹平,与单次搏动特别相关的问题在中位搏上问不出来。
Q6:界标是人工标的还是算法标的?
官方用「半自动」这个词:先算出中位搏,再在向量合成导联上跑自动算法标出五个界标,包括 P 波起点、QRS 起点、QRS 终点、T 波峰、次 T 波峰和 T 波终点。官方没有说明是否逐条人工复核。
Q7:能不能直接拿它训练 QT 自动测量模型?
可以用于开发与调试。但要知道它的标签是半自动界标、对象是压缩后的中位搏。用它当训练集没问题,用它当唯一评测基准会低估模型在原始逐搏信号上的误差。
Q8:22 个人为什么能做出有意义的结论?
因为用的是交叉设计。每个人在五个药物状态下被反复观察,比较发生在同一个人体内,个体间差异被消掉。这样做的比较效率远高于同等人数的平行分组试验,代价是总观察次数多、周期长。
Q9:它覆盖了哪些导联?
标准十二导联,即 I、II、III、aVR、aVL、aVF、V1 至 V6。每条记录的十二路信号按导联顺序存放在同一个 .dat 里,导联名写在头文件的信号行末尾。
Q10:能不能用它研究噪声或信号质量?
不适合。片段由 Antares 软件在每时点择优抽取三份心率稳定、质量最佳的十秒记录,噪声与差质量片段已被主动筛掉。研究信号质量应选保留原始佩戴或长时连续记录的数据集。
Q11:许可能不能商用?
ODC-BY 1.0 允许包括商业用途在内的使用,条件是署名。官方要求引用 Johannesen 等人 2016 年的原始论文,并按平台推荐格式一并引用 PhysioNet。
Q12:它会更新吗?
官方只列出一个版本 1.0.0,2016 年 9 月 15 日发布,之后没有修订记录。临床试验档案类数据集的普遍做法是不再更新,引用时以该版本的 DOI 固定。
术语表
| 术语 | 解释 |
|---|---|
| ECGDMMLD | 本库简称,字母取自五个给药组的药名 |
| QT 间期 | QRS 起点到 T 波终点的时长,反映整条心室复极 |
| J 点 | QRS 复合波结束、ST 段开始的位置 |
| J-Tpeak | J 点到 T 波峰值,主要反映动作电位平台期 |
| Tpeak-Tend | T 波峰值到 T 波终点,主要反映晚期复极 |
| QTc | 心率校正后的 QT 间期 |
| hERG | 一种钾通道基因,其阻滞剂会延长复极 |
| 迟钠电流 | 平台期持续的钠内流,阻滞可缩短平台期 |
| 多非利特 | 强 hERG 阻滞剂,本库的主要阳性对照 |
| 莫西沙星 | 抗菌药,本库的第二种阳性对照 |
| 美西律 | 迟钠电流阻滞剂,口服给药 |
| 利多卡因 | 迟钠电流阻滞剂,静脉给药 |
| 地尔硫卓 | L 型钙通道阻滞剂 |
| 交叉试验 | 同一受试者依次接受多种处理的试验设计 |
| 洗脱期 | 两次给药之间留出的让药效消退的时间 |
| 双向盲法 | 受试者与研究者均不知分组 |
| 随机化编号 | 随机分配系统给出的受试者编号 RANDID |
| 给药期 | 试验的一个处理阶段,本库共五期 |
| 时点 | 相对给药时刻的采样时间 |
| 中位搏 | 逐导联多搏同步后取中位数得到的代表搏动 |
| 界标 | 波形上的关键时间点,如 QRS 起点、T 波终点 |
| 向量合成导联 | 由多导联合成、用于统一标注的单条导联 |
| MIT 格式 | 由头文件与二进制信号文件构成的波形格式 |
.hea 与 .dat |
头文件与信号文件 |
.atr |
注释文件,本库存放界标 |
| ODC-BY 1.0 | 开放数据共享署名许可 |
| CiPA | 一个国际合作的心脏安全评价计划 |
| 暴露-反应分析 | 用血药浓度与效应的关系描述药物作用 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 受试者数 | 22 | 官方摘要 | 官方页面 |
| 年龄范围 | 18 至 35 岁 | 官方摘要 | 官方页面 |
| 给药期数 | 5 | 官方摘要 | 官方页面 |
| 期间间隔 | 一周 | 官方方法节 | 官方页面 |
| 采集采样率 | 500 Hz | 官方方法节 | 官方页面 |
| 幅度分辨率 | 2.5 微伏 | 官方方法节 | 官方页面 |
| 发布采样率 | 1000 Hz | 官方方法节 | 官方页面 |
| 时点数 | 14 | 官方方法节 | 官方页面 |
| 每时点份数 | 3 | 官方方法节 | 官方页面 |
| 片段时长 | 10 秒 | 官方方法节 | 官方页面 |
| 原始片段数 | 4211 | 官方文件说明 | 官方页面 |
| 导联数 | 12 | 官方文件说明 | 官方页面 |
| 每期采血数 | 12 | 官方摘要 | 官方页面 |
| 界标数 | 5(次 T 波峰时 6) | 官方文件说明 | 官方页面 |
| 发布版本 | 1.0.0 | 官方页面 | 官方页面 |
| 发布日期 | 2016-09-15 | 官方页面 | 官方页面 |
| 许可 | ODC-BY 1.0 | 官方页面 | 官方页面 |
| DOI | 10.13026/C2D016 | 官方页面 | 官方页面 |
| 注册号 | NCT02308748 | 官方页面 | 官方页面 |
| 整包体积 | 未标注 | 官方页面未给出 | 未核实 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 受试者数、年龄范围、给药期结构、采集参数、发布采样率、时点数、每时点份数、片段时长、原始片段数、导联数、采血次数、界标构成、版本、发布日期、许可、DOI、注册号,均来自项目主页的摘要与方法节。这些数字在页面上有明确文字表述,可逐句定位。
第二层:论文摘要。 迟钠电流阻滞与钙电流阻滞的组合设计、J-Tpeak 与 Tpeak-Tend 作为分段指标的思路、三类电流在复极不同时段的作用方向,来自 Clinical Pharmacology & Therapeutics 2016 年那篇论文的摘要。摘要提供了机制层面的一致性检验,但没有给出逐条记录的细节。
第三层:未核实。 整包体积、单条文件的确切字节数、CSV 各列名与定义、受试者性别比例、实际完成全部时点的人数分布、界标是否经人工复核、raw 子目录实际采用哪一套编号。这些内容或未在官方页面出现,或需要下载数据才能确认。本次核对时官方文件区显示地区不可用,故以「未核实」标注,正文中不作推断。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | ECGDMMLD v1.0.0 | https://physionet.org/content/ecgdmmld/1.0.0/ | 规模、结构、边界数据来源 |
| 2 | 该库文件目录 | https://physionet.org/files/ecgdmmld/1.0.0/ | 清单与文件 |
| 3 | Johannesen L. 等,Clinical Pharmacology & Therapeutics 2016;99(2):214–223 | https://doi.org/10.1002/cpt.205 | 设计思路与机制结论 |
| 4 | 数据集 DOI | https://doi.org/10.13026/C2D016 | 版本定位 |
| 5 | PhysioNet 平台综述(2026) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 6 | 试验注册信息 | https://clinicaltrials.gov/study/NCT02308748 | 试验方案追溯 |
| 7 | ECGRDVQ(同期姊妹库) | https://physionet.org/content/ecgrdvq/ | §2.5 与 §6.1 对比 |
| 8 | Europe PMC 检索:迟钠电流与长 QT | https://www.ebi.ac.uk/[europepmc](https://www.qianfanghub.com/ai-ready-dataset/europepmc/1353)/ | §7.4 的外部用法 |
附录 D:任务代码
任务一:按给药期与时点建立索引
import pandas as pd
clin = pd.read_csv("SCR-003.Clinical.Data.csv", encoding="utf-8-sig")
print(list(clin.columns)[:12])
#-- 先看列名,再按说明文件核对含义
#-- 按受试者与给药期分组,数每个格子的记录数
if {"RANDID", "period"}.issubset(clin.columns):
grid = clin.groupby(["RANDID", "period"]).size().unstack(fill_value=0)
print(grid.head())
print("总行数", len(clin), "受试者数", clin["RANDID"].nunique())
else:
print("列名与预期不符,请先读字段说明")
这段代码不统计分布,只用来确认索引结构:每个受试者在每个给药期下有多少条记录。若某一格为零,说明该受试者在该期缺失,后续比较要避开这一格。
任务二:检查中位搏界标的完整体
import os
import wfdb
import numpy as np
def check_beat(stem):
ann = wfdb.rdann(stem, "atr")
s = np.asarray(ann.sample)
if len(s) < 5:
return stem, len(s), "界标不足"
if not np.all(np.diff(s) > 0):
return stem, len(s), "界标非单调"
return stem, len(s), "ok"
bad = []
for sub in sorted(os.listdir("medians")):
p = os.path.join("medians", sub)
if not os.path.isdir(p):
continue
for fn in sorted(os.listdir(p)):
if fn.endswith(".hea"):
stem, n, st = check_beat(os.path.join(p, fn[:-4]))
if st != "ok":
bad.append((stem, n, st))
print("异常", len(bad))
for row in bad[:10]:
print(row)
这段把「界标是否齐全、是否按时间顺序排列」写成可执行的断言。它替代不了人工核查,但能在批量处理前先把明显不合规的记录挑出来。
任务三:同一受试者两期的分段对比
import wfdb
def segs(stem):
ann = wfdb.rdann(stem, "atr")
s = ann.sample
j, tp, tend = s[2], s[3], s[-1]
return {"J-Tpeak": int(tp - j), "Tpeak-Tend": int(tend - tp), "QRS-T": int(tend - s[1])}
a = segs("medians/1001_1_5_1")
b = segs("medians/1001_2_5_1")
for k in a:
print(k, a[k], b[k], b[k] - a[k])
#-- 差值单位为采样点,除以 1000 得秒
这是 §4.2 的案例的最后一环:把两期的分段时长并排放,看两段各自的变化方向是否相反。若出现「一段变长、一段变短、总和几乎不变」的情形,正好说明只测 QT 会把机制差异掩盖掉。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | DMML 是五个药名的首字母,不是数据挖掘 | 决定你读完名称后的第一反应对不对 |
| 2 | 22 人但五期交叉,比较效率高于人数 | 决定它能不能回答机制问题 |
| 3 | 采集 500 Hz、发布 1000 Hz 是两个环节 | 决定能不能谈高频细节 |
| 4 | 界标是半自动的,中位搏是压缩的 | 决定什么任务能放心用 |
| 5 | 它测的是复极分段,不是心律分类 | 决定它该被放在哪条流水线里 |
编辑说明
核对于 2026 年 10 月 28 日完成。核对方式为直接访问 PhysioNet 项目页 https://physionet.org/content/ecgdmmld/(经 301 跳转到 /1.0.0/,最终返回 HTTP 200),逐段读取摘要、实验方法、文件说明、访问策略与引用信息;另检索 Europe PMC 获取 Johannesen 等 2016 年论文摘要,用于核实机制层面表述。核心数字中,受试者数、给药期、时点数、每时点份数、采集与发布采样率、片段时长、原始片段数、界标构成、版本、日期、许可、DOI、注册号,均可直接在官方页面文字中定位。
未覆盖的内容包括:整包体积与单条文件字节数(官方页面未标注,且本次核对时文件区显示该地区不可用,files/ 与 get-zip/ 路径均返回 403 或跳转,故不作数值推断);CSV 的实际列名与定义(说明文件同样不可访问);受试者性别比例与各时点的实际完成人数(需读表才能确认);界标是否经人工复核(官方仅称半自动,未进一步说明);raw 子目录实际采用受试者编号还是 RANDID 编号(官方表述为「或」,两种口径并列保留)。文件名示例中的分段方式仅用于示意头文件结构,不代表官方命名规则,正文已提示以 CSV 与目录为准。
本稿按 v3 口径处理官方表述中的两处并列:采集采样率与发布采样率、raw 子目录的两种编号方式,均如实并列呈现,不判断哪一方为准。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- ecgrdvq — 共享标签:生理信号 / 心电信号 / 药物安全 / 心血管疾病
- ecgcipa — 共享标签:生理信号 / 心电信号 / 药物安全 / 心血管疾病
- multimodal-surgery-anesthesia — 共享标签:生理信号 / 药物安全 / 心血管疾病
- wctecgdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ahadb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- chfdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- crisdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- cudb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ltdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ltstdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

