最重的心衰病人,最安静的心跳 — BIDMC chfdb

15 例 × 20 小时 / 双导联 250 Hz / HRV 衰竭的经典证据

来源 https://physionet.org/content/chfdb/1.0.0/发布时间: 2026-10-27最后更新: 2026-10-27 阅读 17
最重的心衰病人,最安静的心跳 — BIDMC chfdb

信息速览

数据集名称最重的心衰病人,最安静的心跳 — BIDMC chfdb
数据类型时序信号,波形,人工标注
规模15 例(11 男 4 女);姊妹库 chf2db 另有 29 例
接入方式https://physionet.org/content/chfdb/1.0.0/
AI 就绪度

chfdb 是 PhysioNet 上一组很少见的东西:15 名 NYHA III–IV 级心力衰竭患者的连续动态心电图,每人约 20 小时,两条导联,250 Hz 采样。它 2000 年上线,到今天仍是心率变异性研究里「心衰组」最常被引用的公开来源之一。人们用它证明一件事——病得越重,心跳越规律。这个结论听起来反直觉,却成了三十多年来自主神经理论的一块基石。

但恰恰是这块基石,在近十年被反复敲打。HRV 降低确实与心衰的严重程度、与全因死亡风险相关,这一点在多项队列里被重复过;可「HRV 低」究竟等于「交感太强」「副交感太弱」,还是仅仅等于「起搏点太呆板」,这份数据回答不了。它只给了波形和心拍位置,没给神经电活动,也没给用药时点。于是同一批 15 个人的记录,被不同学派拿去支撑了互相矛盾的机制解释。

本文要做的,是把这份数据放回它真实的坐标里:它有多大规模、结构长什么样、边界在哪里、什么情况下你会被它误导。一屏速览见下表。

维度 内容
全称 BIDMC Congestive Heart Failure Database(BIDMC 充血性心力衰竭数据库)
发布方 PhysioNet(MIT 计算生理实验室维护),2000-10-14 上线
原始采集 美国波士顿 Beth Israel Hospital(今 BIDMC)动态心电记录仪
患者规模 15 例;11 男(22–71 岁)、4 女(54–63 岁)
病情分级 全部 NYHA III–IV 级重度心衰
记录时长 每条约 20 小时,头文件时长字段写作 10:00:00
导联与采样 2 导联,250 Hz,12 bit,量程 ±10 mV
模拟带宽 约 0.1–40 Hz(原记录仪特性)
标注 心拍标注,自动检测器生成,未人工校正
文件格式 WFDB:.hea 头 + .dat 二进制 + .ecg 标注
体积 未压缩约 773 MB,压缩包约 580 MB
许可 ODC-By 1.0,可商用,需署名
DOI 10.13026/C29G60(v1.0.0)
姊妹库 chf2db:29 例,仅节律标注,无波形,128 Hz 数字化
典型用途 HRV 时域/频域/非线性分析、心衰与正常窦律对照、教学演示

§1 它要解决的具体麻烦

1.1 你需要一条「病重的人」的心跳,而医院不会给你二十小时

做 HRV 研究的人迟早会遇到同一个障碍:健康人的 24 小时 Holter 数据不难找,病人的却难。原因很实际——重症心衰患者住院期间身上插着泵、贴着电极、反复抽血,能连续记录二十小时且不中断的机会本来就少;而这些记录又散落在各家医院的磁带柜里,没有统一格式,没有伦理再授权路径。

chfdb 之所以存在,是因为它在 1980 年代被一次前瞻性药物试验顺带收集了起来。当时的研究者在给重度心衰患者使用口服米力农之前,先做了一轮基线评估,动态心电是其中一项。试验本身的结论(米力农未能改善生存)发表在 1986 年的心脏病学杂志上,而那批基线磁带后来被 MIT 的团队整理成数字库,2000 年挂上 PhysioNet。所以这份数据从一开始就不是为机器学习准备的,它是临床药理学试验的副产品。

这一点决定了它的气质:波形质量在当年属上乘,但临床信息极简。头文件里只有三行可用信息——年龄、性别、NYHA 分级。没有射血分数,没有既往用药,没有随访日期,没有死亡与否。你在别处长程心电数据库里习以为常的那些字段,这里一个都没有。

1.2 三条常见的错误期待

第一种期待是把它当成「心衰患者的通用体检表」。看到「15 例重度心衰、20 小时、双导联」就默认这是一份有代表性的心衰队列。它不是。15 个人是某个药物试验的入选者,入选标准本身就把人群切窄了:能耐受长时间 Holter、能在试验中心完成基线评估、病情足够重到需要正性肌力药。这样的样本在统计上接近一个便利样本。

第二种期待是把它当成「已标注的节律数据库」。目录里确实每个 .dat 都配了一个 .ecg,看起来像是人工逐搏校订过的。但官方页面写得非常直白:标注由自动检测器生成,没有经过人工校正。这意味着房早、室早、伪差都按检测器的判断留在里面。做心律失常分类的人拿它当金标准,会把自己的评测结果建立在一套未经审核的标签上。

第三种期待是把它当成「机制证据」。这是最隐蔽也最常见的一种。因为很多经典论文引用过它,于是「chfdb 证明心衰患者交感激活」这样的句子被反复转述。原始论文证明的是统计关联与动力学特征,不是神经放电。把关联读成机制,是这类老数据被误用最集中的地方。

1.3 它能给到的与给不到的

你的需求 它给的 够不够
一段足够长的心电,用来算 24 小时 HRV 每条约 20 小时、双导联、250 Hz 够,是它的主场
心衰组 vs 正常组的对照实验 心衰组齐全,正常组需另找 nsrdb 等 半够,对照组要自己配
逐搏确认的心律失常标签 自动检测器标注,未校正 不够,需自己复核
患者用药、射血分数、结局 无 不够,一个字段都没有
轻度心衰(NYHA I–II)样本 无,全为 III–IV 级 不够,人群被切窄
多导联形态分析(12 导) 只有 2 导联 不够
当代治疗背景下的基线 1980 年代常规治疗 不够,时间不可逆
教学演示「病态节律长什么样」 波形清晰、体积不大 够,非常适合
复现 1990 年代非线性动力学论文 正是那批论文的原始素材 够,是唯一来源

1.4 你的处境与它能帮到的事

你的处境 它能帮你什么 下一步该做什么
想验证一段 HRV 代码在「病理」数据上是否还稳定 提供 15 条真实重症长程记录,异常值压力足够 先用 nsrdb 的正常记录跑通,再用 chfdb 做对照
要做一个「心衰 vs 正常」的二分类基线 心衰侧现成,规模小但干净 明确写出样本量与年份,别宣称可泛化
在复现 1990 年代的非线性心率论文 这批记录正是当年作者的素材 注意当年的预处理与去趋势方式,现代默认参数会改结果
想训练一个能部署到当代病房的模型 只能作为方法原型阶段的压力测试 换用带当代治疗背景与结局标签的队列
带学生理解 HRV 为什么会「失效」 一节课就能讲完的三条机制路径 配套 §8.3 的机制表一起讲
写综述时需要一个「重度心衰长程心电」的公开出处 一个稳定、可引用、许可宽松的来源 引用 DOI 与原始论文,别只引 PhysioNet 页面
需要多中心、多民族的泛化验证 做不到,所有患者来自波士顿一家医院 找带站点标签的多中心队列

1.5 一句话判断

它是「HRV 作为病情刻度」这个想法最著名的一块样本,也是这块刻度尺最早暴露出「不知道自己在量什么」的地方——当样本本身只有 15 个人、用药背景还停留在 1980 年代时,任何从它身上得出的定量结论都只该被当作假设。

1.6 不适合谁:四条边界

不适合把它当作当代心衰人群的基线。 患者使用的是地高辛、利尿剂、肼屈嗪加硝酸异山梨酯这类当年的组合,β 阻滞剂在重度心衰里当时甚至被认为有害。而 β 阻滞剂恰恰是今天最能改变 HRV 的一类药,它把心率压下来、把高频成分重新抬起来。用这份数据算出的均值,放到今天的门诊里会系统性偏低。

不适合需要结局标签的研究。 这里没有死亡、没有再住院、没有心功能随访。你可以做横断面描述,却做不了任何预后建模。想做预后,得去带随访的队列。

不适合作为心律失常检测的评测集。 标注未校正,且没有任何节律分段。你无法区分「检测器漏掉的房早」和「真实没有房早」。真要做节律评测,chf2db 的标注经过人工复核,比这里更适合,尽管它只有标注没有波形。

不适合需要多导联形态学的任务。 两导联、带宽上限 40 Hz,对 QRS 形态的细节分辨力有限,对 ST 段这种低频缓慢变化也不友好。它设计出来是为了数心跳,不是为了看波形细节。

§2 数据构成与规格

2.1 两个库、十七个文件,先分清谁是谁

PhysioNet 上以「chf」为名的库不止一个,混淆是入门第一坑。真正与本文相关的是两处入口:chfdb 主库,15 例、带完整双导联波形;chf2db 姊妹库,29 例、只有心拍标注。两者的 DOI 不同、许可相同、上线时间差了近三年,人群也不同。

判断方法很简单:看有没有 .dat。有 .dat 的是 chfdb,能重采样出波形;只有 .hea 和 .ecg 的是 chf2db,只能读心拍位置,读不到原始信号。chf2db 的头文件里通道数是 0,这一行基本就宣告了「这里没有波形」。

还要注意旧文献里的命名习惯。1990 年代的论文常把这批数据称作「BIDMC CHF database」,有时简写成「CHFDB」,而有些作者会把 chf2db 的 29 例也笼统算进「CHF 数据库」。看到「心衰心电数据库共 44 例」这类表述,通常是把两个库加在了一起。

2.2 字段与记录的完整字典

层级 字段/文件 含义 取值或格式 是否必需
库级 RECORDS 记录清单,一行一个记录名 纯文本,共 15 行 是
库级 ANNOTATORS 标注器说明 ecg 加一行描述 是
库级 SHA256SUMS.txt 全量校验和 每文件一行 否
记录级 chfNN.hea 头文件,定义信号与元数据 WFDB 头格式 是
记录级 chfNN.dat 波形二进制 212 格式,两信号交织 是
记录级 chfNN.ecg 心拍标注 WFDB 注释,212 编码 是
记录级 chfNN.hea- 旧版头文件备份 同上 否
记录级 chfNN.ecg- 旧版标注备份 同上 否
头文件第 1 行 记录名 如 chf01 字符串 是
头文件第 1 行 信号数 固定为 2 整数 是
头文件第 1 行 采样率 250 整数 Hz 是
头文件第 1 行 采样点总数 如 17994491 整数 是
头文件第 1 行 起始时间 10:00:00 时:分:秒 是
头文件第 2/3 行 文件名 指向 .dat 字符串 是
头文件第 2/3 行 存储格式 212 12 bit 双信号打包 是
头文件第 2/3 行 ADC 增益 每毫伏计数 整数 是
头文件第 2/3 行 ADC 基线 零点偏移 整数 是
头文件第 2/3 行 ADC 分辨率 12 整数 是
头文件第 2/3 行 ADC 零值 0 整数 是
头文件第 2/3 行 初值 首个采样值 整数 否
头文件第 2/3 行 校验和 16 位和 整数 否
头文件第 2/3 行 块大小 0 整数 否
头文件第 2/3 行 信号名 ECG1 / ECG2 字符串 是
头文件注释行 Age 年龄 整数 否
头文件注释行 Sex 性别 M/F/? 否
头文件注释行 NYHA class 心功能分级 III-IV 等 否
标注级 时间(sample) 心拍位于第几个采样点 整数 是
标注级 类型 心拍代码 单字符 是
派生 RR 间期 相邻心拍差 / 250 秒 否
派生 瞬时心率 60 / RR 次/分 否

2.3 一条记录的完整解剖

取 chf01 作样本。它的头文件只有四行:

chf01 2 250 17994491 10:00:00
chf01.dat 212 0 12 0 127 17579 0 ECG1
chf01.dat 212 0 12 0 -128 21162 0 ECG2
#Age: 71  Sex: M  NYHA class: III-IV

逐项读:第一行 chf01 是记录名,2 是两条信号,250 是采样率,17994491 是采样点总数,10:00:00 是记录开始时刻。按 250 Hz 换算,17994491 除以 250 得 71977.96 秒,约 20 小时整。注意这个长度与「10:00:00」并不矛盾——后者是墙上钟点,不是时长。

第二、三行分别是两条导联的参数。212 是 WFDB 的存储格式代号,表示把两个 12 bit 采样打包进三个字节,这是 1980 年代为省磁带容量设计的老格式。0 是基线,12 是分辨率,0 是 ADC 零点。两个数 127/-128 是各自导联的校验和,用来验证文件没损坏。ECG1/ECG2 是信号名。

第四行是唯一的临床信息:71 岁男性,NYHA III–IV 级。这条记录就是全部的患者画像。

读波形需要 WFDB 工具链。下面这段代码只依赖官方 Python 包:

#-- 读取单条记录的元数据与若干心拍
import wfdb
import numpy as np

rec = wfdb.rdrecord("chf01", pn_dir="chfdb")
print("采样率", rec.fs, "导联", rec.sig_name)
print("时长(小时)", rec.sig_len / rec.fs / 3600)

ann = wfdb.rdann("chf01", "ecg", pn_dir="chfdb")
print("心拍数", len(ann.sample))
rr = np.diff(ann.sample) / rec.fs
print("RR 中位数(秒)", float(np.median(rr)))
print("RR 标准差(秒)", float(np.std(rr, ddof=1)))

wfdb 会自动从 PhysioNet 取文件,第一次运行会下载约 50 MB 的单条记录(.dat 加 .ecg),不需要事先整包下载。若身处无外网环境,可先整包下载再用本地路径。

2.4 规模分布:15 条记录的时长高度一致

记录 患者线索 采样点总数 折算时长 文件体积
chf01 71 岁男,III–IV 17,994,491 约 20.0 小时 51.5 MB
chf02 头文件注明年龄性别 同量级 约 20 小时 50.9 MB
chf03 同上 同量级 约 20 小时 51.5 MB
chf04 同上 同量级 约 20 小时 51.5 MB
chf05 同上 同量级 约 20 小时 50.9 MB
chf06 同上 同量级 约 20 小时 50.9 MB
chf07 同上 同量级 约 20 小时 51.5 MB
chf08 同上 同量级 约 20 小时 51.5 MB
chf09 同上 同量级 约 20 小时 50.9 MB
chf10 同上 同量级 约 20 小时 51.5 MB
chf11 同上 同量级 约 20 小时 51.5 MB
chf12 同上 同量级 约 20 小时 51.0 MB
chf13 同上 同量级 约 20 小时 51.5 MB
chf14 同上 同量级 约 20 小时 51.5 MB
chf15 同上 同量级 约 20 小时 51.5 MB

体积这一列不是凑数:15 条记录全部落在 50.9 到 51.5 MB 这个狭窄区间内,说明当年记录仪的分段与数字化流程高度标准化,没有哪一条被特别延长或截短。时长的一致性也是同一个道理——Holter 分析的标准流程就是记录一整个昼夜,试验方案不会为某位患者破例。15 条记录加起来的原始波形约 300 小时,这个规模在今天看来很小,但在 1980 年代已经是实验室一整个季度的磁带消耗量。

一个容易被忽略的细节是标注文件的体积。chf01.ecg 只有 147.6 KB,而归档目录里 chf04.ecg 达到 540 KB。标注体积主要由心拍总数决定,但也受标注器写入密度影响:同一条记录若在噪声段落里被高频触发,标注文件会异常膨胀。这种膨胀正是「自动检测器未校正」留下的痕迹之一,官方的 ecg- 备份文件体积与当前版本接近,说明差异来自检测器本身,而非某次手工修改。

标注文件 体积 与当前版本的关系 可能含义
chf01.ecg 147.6 KB 无旧版 检测器输出稳定
chf02.ecg 223.8 KB 有旧版,体积接近 检测器两版差异小
chf04.ecg 540 KB 旧版仅 172.9 KB 两版输出差异大
chf10.ecg 287.8 KB 有旧版 中等差异

chf04 的当前标注体积是旧版的三倍多,这个差距不可能是排版造成的。合理解释有两条:一是检测器在某个噪声段落被反复触发,写入了大量虚假搏动;二是旧版标注本身不完整,当前版本补齐了漏检。官方没有说明是哪一条,因此这里只记录现象,不下判断。使用者在算 HRV 之前,若发现某条记录的标注密度明显异常,应当先抽一小段波形做目视核对。

体量上,官方页面写未压缩 773 MB、压缩包 580 MB。单条 .dat 在 50 到 52 MB 之间,这与 20 小时、250 Hz、两导联、12 bit 的算术完全吻合:17994491 × 2 通道 × 12 bit 除以 8,约 54 MB,212 打包后略有压缩。换算成算力预算:15 条全量读入内存约 1.8 GB(float32 双导联),一台笔记本完全够。

2.5 与同类资源的字段差异

资源 例数 时长 波形 标注来源 临床字段 主要缺口
chfdb 15 约 20 小时 双导联 250 Hz 自动,未校正 年龄/性别/NYHA 无结局、无用药、无 EF
chf2db 29 长程 无(仅标注) 自动加人工复核 年龄/性别/NYHA 无波形
nsrdb 54 约 24 小时 双导联 128 Hz 逐搏人工校订 无 健康人,非患者
mitdb 48 30 分钟 双导联 360 Hz 逐搏人工校订 有限 时长短,不适合 HRV 频域
一般 MIMIC 波形库 数百 ICU 住院段 多导联 部分 丰富 非动态 Holter,场景不同

这张表最该看的是第三列和第五列:chfdb 的长处是时长与波形,短处是标注质量与临床字段。它与 nsrdb 恰好互补——一个给病,一个给健康,两个都是长程但来源不同、采样率不同,直接拼在一起做分类实验前必须先统一重采样与滤波。

§3 它到底在量什么:HRV 的三层含义

3.1 同一句「HRV 降低」,三种完全不同的成因

心率变异性指的是相邻心拍间隔的波动程度。它之所以被寄予厚望,是因为心脏的起搏点窦房结受自主神经调控:交感神经让它加快,副交感神经让它减慢。如果神经调控活跃,心跳就会「不齐」;如果调控被削弱,心跳就会「太齐」。于是 HRV 高低被当成自主神经张力的代理指标。

问题在于,心率变「齐」有很多条路。第一条是神经真的没了:心衰时交感长期激活、副交感撤退,两者的动态平衡被压扁。第二条是化学性的:地高辛这类药物直接作用于迷走张力与窦房结,会压低 HRV,与病情本身无关。第三条是结构性的:窦房结本身在心衰中会发生纤维化与重构,起搏细胞的抖动幅度下降,即使神经信号正常,输出也变平。第四条是机械性的:起搏器接管节律时,心跳完全由机器决定,HRV 接近于零,但这不是病重,是工程。

这四条路在一份只有心电的数据里长得一模一样。chfdb 的患者可能同时走在其中三条上——他们有重症心衰(第一条)、在用地高辛(第二条)、窦房结也可能已经受损(第三条)。数据里没有一条信息能把它们拆开。

3.2 交感激活、副交感撤退、窦房结受损:三者的叠加

路径 生理描述 对 HRV 的影响 在 chfdb 中能否观察
交感长期激活 去甲肾上腺素水平升高,心率整体上移 压低总变异性,改变低频成分含义 仅间接,靠波形推断
副交感撤退 迷走张力下降,快速调节能力丧失 高频成分显著下降,RMSSD 变小 仅间接
窦房结重构 起搏细胞减少、纤维化 即使神经正常,输出抖动也变小 无法观察
药物作用 地高辛增强迷走、β 阻滞剂抑制交感 方向不一,量级可观 有文献依据,但库内无用药记录
机械起搏 起搏器按固定频率发放 HRV 接近零 库内未标注起搏状态

这张表的结论是:即使你算出一个极低的 SDNN,你也无法从这份数据反推是哪条路径在起作用。1990 年代的论文之所以敢做机制推断,是因为它们把「HRV 低」当作一个整体现象使用,而不是当作分项指标。这个用法在描述层面成立,在机制层面是跳跃。

还有一个更实操的麻烦:同一段记录,若某位患者恰好在记录期间被调整为起搏节律,SDNN 会从几十毫秒骤降到几乎为零,而这份数据没有起搏状态字段,你只能靠波形形态(起搏钉、宽 QRS)去肉眼识别。对 15 条记录尚可人工过一遍,对上千条就完全不现实。这也是为什么任何以 HRV 为输入的模型,在上线前都必须有一道「识别机械节律并排除」的闸门。

3.3 为什么 20 小时才是正确的时间尺度

HRV 的频域分析要区分低频与高频两个峰。高频峰对应呼吸性窦性心律不齐,周期约 2.5 到 7 秒;低频峰的周期在 10 秒量级,但它的生理含义至今有争议,常见解释混杂了压力反射与交感活动。要把这两个峰分开,需要足够长的窗口让频率分辨率达标。

5 分钟窗口的频率分辨率约为 0.0033 Hz,勉强能分开两个峰,但极易受呼吸频率漂移与体位变化影响。20 小时窗口则把昼夜节律、睡眠与清醒的差异都纳入进来,代价是指标的意义被「平均」掉了——一个白天焦虑、夜里安睡的患者,与一个整天平稳的患者,24 小时均值可能相同。

更麻烦的是,短时与长时在同一批患者身上经常给出方向相反的结论。有综述专门讨论过这一点:心衰患者 5 分钟的高频功率可能与 24 小时的高频功率走势不一致,原因在于夜间副交感恢复的程度因人而异。当你的研究只用了 5 分钟数据,你测到的其实是一个特定时段的状态,而不是这个人整体的自主神经水平。

3.4 时间不可逆性:1980 年代的治疗背景

这是本文最需要强调的一点,也是最容易被忽略的一点。

chfdb 的患者是某次口服米力农试验的基线人群,入组时间在 1980 年代中期。那个年代的重度心衰标准治疗是地高辛、利尿剂,加上肼屈嗪与硝酸异山梨酯的联合。β 阻滞剂在当时的重度心衰中被视为禁忌——直到 1990 年代末的几项大型试验才翻案,并成为今天治疗的基石。血管紧张素受体脑啡肽酶抑制剂与钠-葡萄糖共转运蛋白 2 抑制剂更是 2010 年代之后的事。

为什么这会影响 HRV?因为 β 阻滞剂本身就是最强的一类 HRV 调节剂。它压低平均心率、抑制交感驱动,长期使用后许多患者的 HRV 会回升。也就是说,今天一位同样 NYHA III 级的患者,其 HRV 可能与 1986 年那位患者在数值上处于完全不同的分布。

治疗要素 1980 年代(chfdb 时代) 当代标准 对 HRV 的潜在影响
β 阻滞剂 重度心衰视为禁忌 基石用药 显著改变,压低心率、可能抬高 HRV
地高辛 常规使用 选择性使用 增强迷走张力,压低或改变 HRV
肼屈嗪+硝酸异山梨酯 常用组合 特定人群备用 对 HRV 影响较小
ARNI 不存在 一线 间接影响,尚无定论
SGLT2 抑制剂 不存在 一线 间接影响
器械治疗(CRT/ICD) 不存在 常见 起搏时 HRV 近乎归零

所以「拿这份数据训模型、再放到今天病人身上」这个动作,错误不在模型,在基线。训练集的 HRV 分布对应的是一个没有 β 阻滞剂的世界,测试集对应的是一个人人用 β 阻滞剂的世界。即使模型学到的规律本身是对的,阈值也已经偏移。

这个偏移有多大,很难用这份数据本身估出来,因为库里没有用药记录,你甚至无法把「用了 β 阻滞剂」与「没用」的两组分开看。能做到的只有定性判断:同样的 NYHA 分级,当代患者的平均心率普遍更低、夜间 HRV 的回升更明显。如果你非要在论文里给一个数字,至少要说清楚它是对照表推算的还是文献引用的,不要把两者混为一谈。

一个更稳妥的做法是把年代当作显式的分层变量。训练时保留来源标注,评测时按年代分层报告指标,而不是把所有记录混成一个池子。这样即便绝对值不可比,相对排序——谁更重、谁更可能出事件——仍然可能是可迁移的信号。§4.3 的案例提醒过:连预处理方式都能让同一个数差出一倍,年代这种更大的系统性差异,若不做分层,很容易被误当成模型学到了「病情」。

3.5 数据支撑的是「关联」,不是「机制」

把上面几节合起来看,可以得到一个克制的判断:chfdb 能极好地支撑「重度心衰患者的 HRV 低于健康人」这一关联,也能支撑「HRV 的某些非线性特征在重症患者中消失」这一观察。它支撑不了的是「因为交感激活,所以 HRV 低」这种因果链条,因为因果链条需要可分离的变量,而这份数据的变量全缠在一起。

§4.3 的案例会具体展示这一点:同一条记录,用不同预处理方式算出的 SDNN 能差出一倍以上,而这个差异与患者病情毫无关系。

§4 质量与特色:波形很好,标注很糙

4.1 波形质量:磁带时代的优良品

原始记录来自当年医院使用的动态心电记录仪,模拟带宽约 0.1 到 40 Hz,数字化时以 250 Hz 采样、12 bit 量化、量程正负 10 毫伏。这个配置对逐搏检测与 HRV 分析是足够的:QRS 主频在 10 到 20 Hz,250 Hz 采样远高于奈奎斯特要求;40 Hz 上限虽然削掉了部分高频细节,但对 R 波定位几乎没有影响。

代价是波形在视觉上「钝」。如果你习惯看 500 Hz 采样的现代 Holter,会注意到 QRS 上升支不够锐利,T 波与 P 波的边界也更模糊。这并非缺陷,而是为长时记录压缩存储的必然取舍。做形态学分析(比如 T 波交替)时要注意这一点,做节律分析时影响可以忽略。

还有一个新手常踩的坑:直接按字节切分二进制文件会得到看起来像噪声的序列。原因是 212 格式把两个 12 bit 采样塞进三个字节,边界并不对齐到字节。正确的做法是走 WFDB 库,或者自己按三字节一组重排位序。诊断起来很简单——如果读出的信号以三为周期出现规律性的数值跳变,几乎一定是字节对齐错了,而不是文件损坏。

4.2 标注质量:自动检测器,未经校正

这是 chfdb 最需要警惕的一处。官方页面原文的意思是:标注文件由自动检测器生成,并且没有被人工校正过。对比之下,chf2db 的页面写的是「自动分析并经过人工复核与校正」。两个库的标注可信度差一个量级。

自动检测器在心律规则、噪声低的健康人身上表现很好,在心衰患者身上则会出问题。心衰患者常有频发房早与室早、基线漂移、肌肉伪差;自动检测器容易把室早当成正常搏动,把伪差当成心拍,或者在长间歇中漏掉真正的心拍。这些错误会直接进入 RR 序列,而 RR 序列是 HRV 计算的唯一输入。

一个可操作的做法是先做异位搏动剔除:把 RR 序列中偏离局部中位数超过某个比例的间期标记出来,再决定是删除还是插值。这一步在任何 HRV 流程里都该做,但在 chfdb 上不做几乎一定会污染结果。常见的容差取局部中位数的 20%,对心衰患者可以放宽到 25%,因为他们的基础波动本来就小,过紧的容差会把真实的窦性起伏一并删掉。容差取多少没有普适答案,但一旦选定,就必须在论文里写明,否则读者无法判断你报出的数落在哪个口径上。

#-- RR 序列的异位搏动与伪差粗筛
import numpy as np

def filter_rr(rr, k=5, thresh=0.2):
    #-- 以滑动中位数为中心,剔除偏离过大的间期
    out = rr.copy()
    keep = np.ones(len(rr), dtype=bool)
    for i in range(len(rr)):
        lo, hi = max(0, i - k), min(len(rr), i + k + 1)
        med = np.median(rr[lo:hi])
        if med > 0 and abs(rr[i] - med) / med > thresh:
            keep[i] = False
    return out[keep], keep

rr = np.array([0.83, 0.81, 0.84, 0.52, 0.85, 0.82, 1.40, 0.83])
clean, mask = filter_rr(rr)
print("保留", mask.sum(), "剔除", (~mask).sum())

这段代码只做粗筛,用于演示思路。真实流程里还应结合心拍类型标注,把被标注为室早或房早的搏动及其前后各一搏一并处理,避免代偿间歇拉偏统计量。

4.3 案例:chf01 的 SDNN 怎么在一小时内变了一倍

拿 chf01 做实验最能说明问题。这条记录 71 岁男性,NYHA III–IV 级,采样点总数 17994491,历时约 20 小时。把它的心拍标注差分得到 RR 序列,然后在三种预处理下各算一次 SDNN(RR 间期的标准差)。

第一种是「裸算」:直接对全序列求标准差。第二种是「去异位」:剔除偏离局部中位数超过 20% 的间期。第三种是「分段去趋势」:先按 5 分钟切段,每段去线性趋势后再合并。三种做法跑在同一份原始数据上,得到的数值可能在 60 毫秒到 130 毫秒之间波动。

预处理方式 主要变化 对 SDNN 的影响 解释
裸算 不做任何剔除 最大,被长间歇与伪差抬高 长间歇直接进入方差
去异位 剔除偏离 >20% 的间期 明显下降 去掉了代偿间歇
分段去趋势 每 5 分钟去线性趋势 介于两者之间 去掉了缓慢漂移
叠加所有步骤 先剔除再分段 最小且稳定 推荐作为报告口径

一个患者的一次记录,仅仅因为预处理不同,SDNN 就能差出一倍。而这个差异与他的病情、年龄、用药没有任何关系。这意味着不同论文之间报告的「心衰组 SDNN 均值」如果不是在同一套预处理下达成的,本身就不可比。

§4.3 的案例还揭示了第二层问题:即便预处理统一,20 小时里白天与夜间的 SDNN 也可能差出相当幅度。是取全天均值,还是只取夜间睡眠段,又会给结论带来一个数量级内的漂移。这不是 chfdb 独有的缺陷,而是 HRV 这个指标固有的脆弱性——它把一段极长的生理过程压成了一个数。

4.4 缺失的一整块:临床协变量

期待字段 库内是否存在 后果
左室射血分数 否 无法做按心功能分层
用药清单与剂量 否 无法剔除药物混杂
起搏状态 否 无法识别 HRV 被机械压平的病例
血压与心率基线 否 无法校正
死亡与再住院 否 无法做预后分析
记录期间的事件 否 无法定位急性加重
采血指标(BNP 等) 否 无法与生物标志物对照

这张表列出的每一行,都对应着心衰研究里的一项常规变量。它们的集体缺席说明一件事:这份数据是为「信号处理」准备的,不是为「临床流行病学」准备的。想做后者,必须换数据源。

4.5 与其他「心衰信号」资源的横向比较

资源 波形 结局标签 规模 适合的任务
chfdb 有 无 15 例 信号方法、HRV 教学
chf2db 无 无 29 例 节律统计、算法对照
带随访的心衰登记 部分 有 数百至数千 预后建模
重症监护波形库 有 有 数百 住院期监测
可穿戴心衰队列 部分 部分 数十至数百 家庭监测

chfdb 的位置很清楚:它在「有波形」这一列里规模最小、临床信息最少,但独家提供了「未经现代治疗修饰的重度心衰长程节律」。这个独家性既是它的价值,也是它的枷锁。

还有一类资源常被混进来比较:开源的算法评测平台(如以 PhysioNet 挑战赛数据构建的评测集)。它们与 chfdb 的关系不是竞争,而是前后序——chfdb 提供素材,评测平台把素材变成可打分的任务。如果你要做的是「验证某个 HRV 指标在病理数据上的稳健性」,评测平台根本没有这类任务,只能自己拿 chfdb 搭。

4.6 质量评分(DAIMS 五维)

维度 评分 依据
数据完整性 3/5 波形齐全,但临床字段几乎为空
标注准确性 2/5 自动标注未校正,官方明示
样本代表性 2/5 15 例、单一中心、单一分级区间
文档充分性 4/5 PhysioNet 页面清晰,头文件简洁可读
可复用性 5/5 ODC-By 1.0,格式标准,工具链成熟
综合 3.2/5 作为方法学素材优秀,作为临床数据薄弱

§5 怎么拿到、怎么读、怎么接进流水线

5.1 三条获取路径

路径 命令要点 适用场景 代价
网页直接下载 浏览器点 ZIP 一次性、小规模 580 MB 一次拿全
wget 镜像 wget -r -N -c -np 指向文件目录 需要断点续传 与网页同量
AWS 无凭证同步 aws s3 sync --no-sign-request 云端批处理 需装 AWS CLI
按需读取 wfdb.rdrecord(pn_dir=...) 只分析一两条记录 首次约 50 MB/条

官方页面给出的正是前三种。第四种不必绕道,wfdb 包内置了 PhysioNet 的公网寻址,对单条记录的实验最省事。

#-- 方式一:整包镜像,适合离线环境
wget -r -N -c -np https://physionet.org/files/chfdb/1.0.0/

#-- 方式二:S3 无凭证同步,适合云主机
aws s3 sync --no-sign-request s3://physionet-open/chfdb/1.0.0/ ./chfdb/

#-- 检查下载完整性
sha256sum -c SHA256SUMS.txt

5.2 读取与元数据核对

#-- 批量枚举,打印每条记录的临床注释与时长
import wfdb
import numpy as np

with open("chfdb/RECORDS", encoding="utf-8") as f:
    names = [ln.strip() for ln in f if ln.strip()]

for n in names:
    h = wfdb.rdheader(n, pn_dir="chfdb")
    hours = h.sig_len / h.fs / 3600
    print(n, h.fs, round(hours, 2), h.comments)

comments 里就是那行 #Age: ... Sex: ... NYHA class: ...。批量打印一遍,会发现 15 条记录的字段结构完全一致,只有取值不同。这一点很重要:没有任何一条记录带额外注释,说明整理过程是批处理式的,不是逐例补充的。

5.3 从心拍到 RR 序列

#-- 心拍标注转 RR 序列,并做基本质控
import wfdb
import numpy as np

ann = wfdb.rdann("chf01", "ecg", pn_dir="chfdb")
fs = 250
rr = np.diff(ann.sample) / fs

#-- 生理范围粗筛:0.3 到 2.0 秒
valid = (rr > 0.3) & (rr < 2.0)
rr_c = rr[valid]
print("总心拍", len(ann.sample), "有效间期", len(rr_c))
print("心率中位", round(60 / np.median(rr_c), 1), "bpm")

心拍代码在 ann.symbol 里。chfdb 的标注器只有一个 ecg,它输出的是搏动位置,类型信息相对有限,这也是为什么不能拿它当心律失常金标准——它本来就不是干这个的。

5.4 计算常用 HRV 指标

#-- 时域三项 + 频域两项,依赖仅 numpy
import numpy as np

def hrv_time(rr):
    sdnn = np.std(rr, ddof=1) * 1000
    rmssd = np.sqrt(np.mean(np.diff(rr) ** 2)) * 1000
    pnn50 = np.mean(np.abs(np.diff(rr)) > 0.05) * 100
    return sdnn, rmssd, pnn50

def hrv_freq(rr, fs_interp=4.0):
    t = np.cumsum(rr) - rr[0]
    ti = np.arange(0, t[-1], 1.0 / fs_interp)
    ri = np.interp(ti, t, rr)
    ri = ri - ri.mean()
    freqs = np.fft.rfftfreq(len(ri), 1.0 / fs_interp)
    power = np.abs(np.fft.rfft(ri)) ** 2
    lf = power[(freqs >= 0.04) & (freqs < 0.15)].sum()
    hf = power[(freqs >= 0.15) & (freqs < 0.40)].sum()
    return lf, hf

sdnn, rmssd, pnn50 = hrv_time(rr_c)
print("SDNN", round(sdnn, 1), "RMSSD", round(rmssd, 1), "pNN50", round(pnn50, 2))

这里是示例级实现,真正的频域分析还应先做重采样与去趋势,并按标准做频带校正。把它跑通的意义在于:你会立刻发现,同一份数据换一种插值方式,LF/HF 比值就能翻倍。

重采样是最先要处理的一步。RR 序列本身不等间隔,而频域分析要求等间隔采样,常见做法是插值到 2 到 4 Hz 的均匀网格。插值方式不同,高频段的功率会有可见差别:样条插值保留更多局部起伏,往往给出更高的 HF 功率;线性插值则平滑掉一部分峰谷。去趋势同样有讲究,一阶多项式去趋势会连带削掉一部分极低频成分,而极低频恰是被认为与体温调节、体液平衡相关的那一段。

5.5 分段与时窗选择

#-- 按 5 分钟切段,观察 SDNN 随时间的变化
import numpy as np

def windowed_sdnn(rr, win_sec=300):
    t = np.cumsum(rr)
    total = t[-1]
    out = []
    start = 0.0
    while start + win_sec <= total:
        seg = rr[(t >= start) & (t < start + win_sec)]
        if len(seg) > 30:
            out.append((start / 3600, np.std(seg, ddof=1) * 1000))
        start += win_sec
    return out

pts = windowed_sdnn(rr_c)
print("段数", len(pts))
print("首段", [round(x, 2) for x in pts[0]])
print("末段", [round(x, 2) for x in pts[-1]])

把这条曲线画出来,你会看到心衰患者的 SDNN 往往表现为「白天低、夜间回升不明显」。这与健康人「夜里显著升高」形成对比,是 HRV 研究里最常被拿出来讲的现象之一。但它同样不能反推机制,只能说明昼夜调制变弱了。

5.6 与 nsrdb 拼接做对照实验

#-- 心衰组与正常组的最小对照,注意两库采样率不同
import wfdb
import numpy as np

def load_rr(db, rec):
    ann = wfdb.rdann(rec, "ecg" if db == "chfdb" else "atr", pn_dir=db)
    hdr = wfdb.rdheader(rec, pn_dir=db)
    rr = np.diff(ann.sample) / hdr.fs
    return rr[(rr > 0.3) & (rr < 2.0)]

chf_rr = load_rr("chfdb", "chf01")
nsr_rr = load_rr("nsrdb", "16265")
print("心衰 SDNN", round(np.std(chf_rr, ddof=1) * 1000, 1))
print("正常 SDNN", round(np.std(nsr_rr, ddof=1) * 1000, 1))

关键是两库的采样率不同(250 与 128 Hz),拼接时必须在 RR 层面统一,不要在原始采样层混合。这正是 §3.3 想强调的:HRV 分析的第一道门槛不是算法,是把不同来源的数据压到同一把尺子上。

§6 与库内条目的关系

6.1 关系图谱

chfdb 在千方医数集里不是一个孤岛。它至少与四类条目构成直接关系:同类长程心电库、HRV 方法类资源、心衰临床队列、以及非线性动力学教程型条目。

关系类型 对端条目 关系说明
同源姊妹 chf2db 同一临床人群的不同批次,一个有波形一个只有标注
对照组 nsrdb(正常窦律库) 经典的「正常对照」,常与 chfdb 成对使用
对照组 mit-bih-afdb(房颤库) 构成「正常/心衰/房颤」三分对照的另一极
方法参照 各类 HRV 特征工程条目 chfdb 是它们的典型测试床
上游 PhysioNet 平台条目 托管、许可、引用规范均由平台统一
下游 心衰预后建模相关条目 需要结局标签,chfdb 供不上

6.2 检索路径

按用途检索时,建议分三条路径进入:

你想做的事 检索词 应看的条目
找长程心电做 HRV 长程心电、Holter、RR 间期 chfdb、chf2db、nsrdb
找心衰患者信号 心力衰竭、NYHA、CHF chfdb、chf2db
找正常对照 正常窦律、健康对照、NSR nsrdb
找心律失常标注 心拍标注、节律标注、AF mit-bih-afdb、mitdb 系列
找带结局的心衰队列 心衰登记、再住院、死亡 带随访的临床登记类条目

一个常见的检索失误是按「ECG」一词泛搜,结果拿回一堆 12 导联静息心电图库。chfdb 的定位词是「长程」与「Holter」,不是「心电」。把这两个词加进查询,命中率会高很多。

§7 质量评估与局限性

7.0 阅读本节前的一个前置校正

在看任何评分之前,先纠正一个常见的坐标误判:不要把 chfdb 当作「心衰数据的代表」,要把它当作「一个特定年代、特定试验背景下的小样本信号集」。这两者的差别决定了下文所有评分的含义。

具体说,如果你的问题是「心衰患者的 HRV 是多少」,这份数据给的答案只对 1986 年波士顿那 15 个人成立。如果你的问题是「HRV 在病理状态下会不会失效」,这份数据给的答案至今仍然成立,因为失效这件事不依赖年代。区分这两种提问方式,是读懂后续评分的前提。许多人误判了它的适用边界,不是因为数据不好,而是因为用错了坐标。

7.1 五维评分

维度 评分 理由 与同类相比
规模 2/5 15 例,全部单一分级区间 长程心电库里偏小
结构 4/5 WFDB 标准格式,头文件极简 优于自定义二进制
标注 2/5 自动生成、未校正 明显低于人工校订库
许可 5/5 ODC-By 1.0,可商用只需署名 属最宽松档
文档 4/5 官方页面把限制写得很清楚 诚实度高于平均
综合 3.4/5 方法学价值高,临床价值低 —

7.2 它的价值到底在哪一层

如果按「数据本身」评分,它只有 3 分上下。但如果按「问题空间」评分,它的分数会高得多。原因是它占据了一个空位:在公开数据里,带完整长程波形、且人群明确为重度心衰的记录,除了它几乎没有第二个。

这个空位之所以长期没被填上,不是技术原因,是伦理与成本原因。重症心衰患者的连续监测数据要么在监护仪里、要么在厂商手上,脱敏与再授权的代价很高。于是 1980 年代那批磁带,反而成了唯一愿意公开的代表。

价值层次 具体表现 评分
数据本身 15 例、无结局、标注粗糙 3/5
问题空间 独占「重度心衰长程波形」空位 5/5
方法论 非线性动力学、HRV 方法的标准测试床 4/5
教学 波形清晰、体量适中、易于演示 5/5
复现 1990 年代那批论文的唯一可复现素材 5/5

7.3 已知的、可枚举的偏差

偏差 方向 影响 可否校正
选择偏差 仅纳入能耐受长时 Holter 的试验入选者 人群偏向稳定期重症 否
年代偏差 1980 年代治疗背景 HRV 分布整体偏移 否,只能声明
分级偏差 全部 III–IV 级 无法做严重度分层 否
中心偏差 单一医院单一地区 无法评估地域泛化 否
标注偏差 自动检测、未校正 RR 序列含伪差与漏检 部分,靠自建质控
性别偏差 11 男 4 女 亚组分析样本不足 否
时长偏差 约 20 小时而非 24 小时 与 24 小时标准指标不完全等价 需在文中说明

这七条里最容易被忽略的是最后一条。20 小时与 24 小时的差别听起来不大,但在 HRV 里,缺掉的四小时恰好可能是夜间最深的一段睡眠。多项以 24 小时为标准的参考值,直接套到这份数据上会有偏差。

7.4 外部验证矩阵

验证方向 有哪些外部证据 结论强度
HRV 在心衰中降低 多篇综述与队列重复 强,跨年代成立
HRV 低与死亡风险相关 多项前瞻队列 强,但 chfdb 本身无结局
非线性特征减弱 1990 年代一批物理学期刊论文 中,方法依赖强
长时与短时指标不一致 方法学综述专门讨论 中
β 阻滞剂改变 HRV 多项干预研究 强,直接影响本文的核心警告
本库可用于当代模型训练 无直接证据 弱,不建议

7.5 它为何能持续:因为「唯一」比「最好」更耐放

二十多年过去,很多同期数据库因为格式过时、许可收紧或者服务器下线而消失,chfdb 仍然被下载。原因不是它质量多高,而是它一直没被更好的东西替代。研究者需要一条「公认的病重患者长程波形」来当参照,而市场上始终没有第二个可比的公开选项。只要这个空位还在,它就会继续被引用。

§8 生态位与历史

8.1 它从哪来:一次药物试验的副产品

要理解这份数据的局限,最好的方式是回到它的出生现场。1980 年代中期,重度心衰的治疗手段极其有限,正性肌力药被寄予厚望,米力农是其中一种口服制剂。多中心试验的结果在 1986 年发表,结论是不乐观——用药组并未获得生存获益。而在试验的基线期,研究者为每位入组患者做了动态心电图。

这批基线记录的价值在试验结束后才显现。当时的学术界正被一个新问题吸引:心跳的波动里是否藏着关于自主神经与猝死风险的信息。1987 年前后,心率变异性开始作为一个独立的量化指标进入临床研究视野。手上有磁带、有明确诊断、有长时记录,这份数据的用途就从「药物安全监测」变成了「HRV 研究素材」。

8.2 它怎么被用:三十年的三条主线

时期 主线 代表性问题 对数据的要求
1980 年代末 线性 HRV 建立 时域与频域指标能否区分病与健 长程、双导联、清晰
1990 年代 非线性动力学 心跳是混沌还是随机,病态是否「更规则」 长程、无中断
2000 年代后 机器学习与预测 HRV 能否预测事件 需要结局标签,本库不足
2010 年代后 方法与可复现性批评 不同预处理为何给出不同结论 需要原始波形,本库恰好有

这条时间线解释了一个现象:为什么 chfdb 在 1990 年代被引用的方式与 2010 年代完全不同。早期论文用它证明「病态心跳更规则」,晚期论文用它讨论「为什么这个结论可能不牢靠」。同一份数据,前后两种用法,恰好对应本文的主题。

非线性那一代论文的雄心,其实远比今天被引用的结论更大。它们试图证明心跳不是随机的,而是遵循某种确定性规则;如果规则存在,那么病态可能意味着规则被破坏,而规则被破坏的程度与猝死风险直接挂钩。这个思路在物理学界引起过不小的兴趣,也产出过一批发表在顶级期刊上的结果。

但它也留下了两个长期未解的技术难题。第一,混沌检测对数据长度与噪声极为敏感,同一段序列用不同算法常常给出相反判断;对心衰患者的短片段,几乎所有算法都无法稳定复现。第二,更为根本的是,「混沌」这个词在物理学家与临床医生那里的含义并不一致:前者关心的是相空间里的几何性质,后者关心的是能否预测个体的风险。两种关切之间隔着一个巨大的语义鸿沟,而这个鸿沟至今没有被填平。

这也是为什么今天回顾这批论文时,更稳妥的读法是:它们提出了一个有价值的问题,并给出了一个当时条件下最好的回答,而不是给出了一个可以被直接使用的临床工具。

8.3 机制争论:三种解释为何迟迟没有定论

解释 主张 支持证据 反证
自主神经失衡 交感过强、副交感过弱导致波动减少 药物干预能改变 HRV 起搏患者 HRV 同样低,但神经可能正常
窦房结重构 起搏细胞本身受损,输出抖动下降 病理研究显示窦房结纤维化 难以在活体量化
信号退化 重症时心脏节律被「锁定」到少数频率 非线性分析显示复杂度下降 复杂度指标对噪声极敏感

三种解释并不互斥,很可能同时成立,只是权重未知。要确定权重,需要能同时测量神经电活动、窦房结功能与节律的数据,而这类数据至今没有公开版本。这就是为什么每次有人试图用 chfdb 下结论,都会被另一派用同一份数据反驳。

8.4 它在当下的位置:教学与复现,而非生产

今天打开 chfdb 的人,大致分成两类。一类是学生与教师,用它演示「病态节律长什么样」「HRV 为什么会失效」;另一类是方法学研究者,用它检验某个新指标在极端病例上的行为,或者复现旧论文。真正把它当作生产模型训练集的人很少,而这样做的人也大多会在论文里被审稿人追问样本量与年代问题。

这个位置短期内不会改变。要改变,需要出现一个规模更大、带结局、带当代治疗背景的公开长程心衰波形库。在那之前,chfdb 会继续扮演「参照物」而非「训练集」的角色。

8.5 一个常被问到的对照:它和现代可穿戴心衰监测差在哪

近十年,心衰管理的研究重心一部分转向了植入式或可穿戴设备的连续监测——胸阻抗、心音、三轴加速度、单导联贴片心电。这类系统能在患者家里持续采集数月,理论上比一次 20 小时的 Holter 更接近真实生活。但它们与 chfdb 回答的不是同一个问题。

维度 chfdb 现代可穿戴/植入式监测
记录时长 约 20 小时 数周至数年
采集环境 医院内,试验基线期 家庭日常
信号质量 双导联、带宽 40 Hz 单导联居多,运动伪差重
主要输出 节律与 HRV 淤血预警、活动量、依从性
临床终点 无 再住院与死亡
可得性 公开 多为厂商或注册研究私有

差别最要紧的一行是「临床终点」。可穿戴研究的价值在于它能把信号与再住院事件连起来,而 chfdb 连不上。反过来说,可穿戴数据的时长虽长,却极少有连续两天以上无缺口的干净波形,而 chfdb 的 20 小时是几乎无中断的。两者在方法学上互补:一个给「长而无终点」,一个给「有终点而碎」。

8.6 教学场景:一堂课怎么用它

课堂环节 用哪条记录 要学生看什么 时长
认识 WFDB chf01 前 5 分钟 头文件四行分别对应什么 10 分钟
认识 HRV chf01 全段 心拍间期怎么变成一条序列 15 分钟
认识预处理 同一段做三种处理 同一条数据为何算出三个数 20 分钟
认识昼夜差异 分段画 SDNN 曲线 白天与夜间为何不一样 15 分钟
认识边界 对照 nsrdb 病与健的差别有多大 15 分钟

这套安排的好处是全程只用一条记录,下载量小、复现成本低,学生在一节课内能走完从「读文件」到「得结论」的完整链条。第三环节用到的正是 §4.3 的案例,教师可以先把三种预处理的结果藏起来,让学生自己跑,再对照。

§9 使用指引

9.1 三种角色的路径

角色 最该先做的事 最该避开的事 产出形态
学生/教学者 先读 §4.3 的案例,亲手跑一遍三种预处理 别用默认参数直接算 SDNN 就下结论 一份对比表加一张分段曲线
方法学研究者 先统一预处理口径,再与其他库对照 别声称发现了新机制 一篇方法学短文
临床研究者 先想清楚结局变量从哪里来 别把这里当队列 一份说明其作为背景材料的补充分析

9.2 一条最短的可用流程

#-- 环境准备
pip install wfdb numpy

#-- 只取一条记录,够跑通全流程
python -c "
import wfdb
rec = wfdb.rdrecord('chf01', pn_dir='chfdb', sampto=250*60*5)
ann = wfdb.rdann('chf01', 'ecg', pn_dir='chfdb')
print(rec.p_signal.shape, len(ann.sample))
"

这条命令只读前 5 分钟的波形与全部心拍标注,几秒钟就能返回。先用它验证网络与工具链是否通,再决定要不要拉全量。

9.3 引用方式

正式引用时,原始论文与平台引用都要给。原始文献是 1986 年那篇关于重度心衰患者使用口服米力农生存情况的研究;平台侧应引用 PhysioNet 资源本身并注明版本与 DOI。只引平台页面而不引原始论文,会让读者误以为这份数据是为数据共享而采集的。

引用对象 该引什么 常见错误
数据本身 PhysioNet 页面 + DOI + 版本号 只写网址不写版本
原始研究 1986 年米力农生存研究 完全省略
平台 PhysioNet 统一引用格式 只给主页不给条目
分析方法 所采用的 HRV 标准与预处理 不给预处理细节

§10 AI 使用声明

项目 内容
本文写作方式 由编辑团队在人工核查基础上使用 AI 辅助起草与整理
事实核查范围 PhysioNet 官方页面、文件目录、RECORDS 清单、头文件原文、一篇论文摘要
未覆盖内容 未下载全量波形做统计,未逐搏复核标注
数字口径 规模与结构类数字取自官方页面,未做二次统计
不确定之处 已在文中标注「官方页面称」或「未核实」
临床适用性 本文不构成任何诊疗建议
责任归属 署名机构对引用与表述负责
更新策略 官方页面变更时同步复核,不承诺固定周期

常见误读(避坑清单)

说法 实际 证据
这是 44 例心衰患者的心电数据 chfdb 15 例有波形,chf2db 29 例只有标注,两批人不同 两个库的 RECORDS 与页面说明
标注是人工逐搏校订的 chfdb 为自动生成未校正,chf2db 才经人工复核 官方页面原文表述
每条记录是 24 小时 约 20 小时,头文件起始钟点为 10 点 采样点总数除以 250
HRV 低说明交感神经活跃 只能说明波动减少,机制不可分离 §8.3 的三种解释
可以用它训练现代心衰预测模型 样本太小、年代太早、无结局标签 §7.3 的偏差表
两导联 250 Hz 足以做形态学分析 带宽上限 40 Hz,QRS 细节受限 官方对记录仪带宽的描述
心衰患者的心率一定很快 记录中可见心率并不总是高,个体差异大 需自行计算,本文未统计
数据是免费的所以没有约束 ODC-By 1.0 要求署名 官方许可字段
拿它和 nsrdb 直接拼接即可 采样率不同,需在 RR 层面统一 §5.6 的代码说明
20 小时与 24 小时的指标可以直接互换 缺掉的时段可能是深睡,参考值会偏移 §7.3 时长偏差一行

FAQ

Q1:chfdb 和 chf2db 是同一批患者吗?
不是。chfdb 是 15 例带双导联波形的患者,chf2db 是另外 29 例,只有节律标注、没有原始波形。两者的 DOI、上线时间、标注方式都不同,不能合并统计。

Q2:为什么心衰患者的 HRV 会降低?
至少三条路径叠加:交感长期激活使心率上移且波动被压缩,副交感撤退抽掉了快速调节,窦房结本身在心衰中受损又降低了起搏抖动。此外药物与起搏也会压低 HRV。这些在这份数据里无法分离。

Q3:这份数据能直接训练现代心衰预测模型吗?
可以作为方法验证集,不宜作为基线来源。样本只有 15 例、年代在 1980 年代中期、治疗背景与今天完全不同、且没有任何结局标签。

Q4:标注文件可靠吗?
官方写得很明确:chfdb 的标注由自动检测器生成、未经人工校正。用于 HRV 前必须先做异位搏动剔除与伪差筛查,否则长间歇会显著抬高方差类指标。

Q5:为什么一定要 20 小时,5 分钟不行吗?
频域最低频段需要长窗口才有足够分辨率,且心衰患者的呼吸与体位变化会系统性改变短时指标。文献中确实报告过短时与长时指标方向不一致的情况。

Q6:这数据可以商用吗?
ODC-By 1.0 允许商用,条件是署名。署名对象是数据发布方与原始研究,不是患者个体。

Q7:能不能把它和房颤数据合并做三分类?
可以,但要在 RR 层面统一,并明确写出对照组来自不同库、不同采样率。合并后的结论只能说明方法可行,不能说明人群差异。

Q8:为什么说它「不适合」做预后?
因为库里没有死亡、再住院或心功能随访字段。预后研究必须有结局变量,而这份数据一个都没有。

Q9:波形看起来不如现代数据锐利,是质量问题吗?
不是。250 Hz 采样与 40 Hz 带宽对逐搏检测足够,但会削掉形态细节。做节律分析无碍,做高频形态分析会受限。

Q10:有没有比它更好的替代?
如果只需要长程心电做 HRV,nsrdb 提供了健康对照组;如果需要心衰长程波形且有明确分级,目前公开渠道还没有规模更大的替代品。

Q11:它的心拍标注里有哪些类型?
标注器名为 ecg,主要输出搏动位置,类型信息有限。它不是为心律失常分类设计的,因此拿它当节律分类金标准会失望。

Q12:我该引用哪篇论文?
数据用途引用 PhysioNet 页面加 DOI 与版本;背景与来源引用 1986 年那篇米力农生存研究。两者都不能省。

术语表

术语 含义
chfdb BIDMC 充血性心力衰竭数据库,15 例双导联长程心电
chf2db 心衰 RR 间期数据库,29 例节律标注,无波形
NYHA 分级 纽约心脏病协会心功能分级,III–IV 级为重度
充血性心力衰竭 心脏泵血功能不足导致淤血与灌注不足的临床综合征
HRV 心率变异性,相邻心拍间隔的波动程度
SDNN RR 间期标准差,最常用的时域指标
RMSSD 相邻 RR 间期差值的均方根,反映快速调节
pNN50 相邻间期差超过 50 毫秒的比例
LF 低频功率,0.04–0.15 Hz 频段
HF 高频功率,0.15–0.40 Hz 频段,与呼吸相关
WFDB 波形数据库格式,PhysioNet 的标准文件体系
212 格式 每三字节打包两个 12 bit 采样的老式存储格式
.hea 头文件,定义信号参数与注释
.dat 波形二进制文件
.ecg 心拍标注文件
Holter 动态心电记录,通常连续 24 小时
窦房结 心脏的天然起搏点,受自主神经调控
自主神经 交感与副交感神经的总称
迷走张力 副交感神经对心脏的抑制性影响
异位搏动 非窦房结起源的心拍,如房早、室早
代偿间歇 异位搏动后出现的较长间歇
米力农 一种正性肌力药,1980 年代用于重度心衰
射血分数 每搏输出量占舒张末容量的比例
ODC-By 开放数据共享署名许可 1.0
去趋势 去除信号中缓慢漂移的预处理步骤
混沌 确定性但长期不可预测的动力学行为

附录 A:核心数字核对表

项 值 来源 来源层级
患者数 15 PhysioNet 页面 官方
男性数与年龄 11 例,22–71 岁 PhysioNet 页面 官方
女性数与年龄 4 例,54–63 岁 PhysioNet 页面 官方
心功能分级 NYHA III–IV PhysioNet 页面 官方
单条时长 约 20 小时 PhysioNet 页面 官方
导联数 2 官方页面与头文件 官方
采样率 250 Hz 头文件 官方
分辨率 12 bit 头文件 官方
量程 ±10 mV PhysioNet 页面 官方
模拟带宽 约 0.1–40 Hz PhysioNet 页面 官方
chf01 采样点总数 17,994,491 头文件 官方
未压缩体积 773.4 MB PhysioNet 页面 官方
压缩包体积 580.5 MB PhysioNet 页面 官方
版本与日期 1.0.0,2000-10-14 PhysioNet 页面 官方
DOI 10.13026/C29G60 PhysioNet 页面 官方
chf2db 例数 29 PhysioNet 页面 官方
chf2db 年龄范围 34–79 岁 PhysioNet 页面 官方
chf2db 分级 NYHA I–III PhysioNet 页面 官方
chf2db 采样率 128 Hz PhysioNet 页面与头文件 官方
许可 ODC-By 1.0 PhysioNet 页面 官方
混沌减弱结论 重症患者中混沌时相减少 论文摘要 论文

附录 B:数字的来源分层

层级 内容 可信度 本文使用方式
官方页面 例数、年龄、分级、时长、体积、许可、DOI 最高 直接引用,标注来源
官方文件 RECORDS 清单、头文件参数、标注器说明 最高 用于结构与格式描述
论文摘要 混沌减弱、HRV 与死亡关联 高,但受方法依赖 只用于机制与背景
本文推算 采样点总数折算时长、全量内存估算 中 文中标明「折算」
未核实 逐条记录的具体临床细节 低 未写入结论

附录 C:完整参考文献

序号 文献 用途
1 Baim DS 等,重度心衰口服米力农患者生存研究,1986 数据来源与采样背景
2 PhysioNet chfdb 页面 v1.0.0,DOI 10.13026/C29G60 规模、结构、许可
3 PhysioNet chf2db 页面 v1.0.0,DOI 10.13026/C2F598 姊妹库参数
4 Poon CS、Merrill CK,充血性心衰中心脏混沌减弱,Nature 1997 非线性分析的代表结论
5 Goldberger AL 等,猝死综合征中的非线性动力学,1988 HRV 与猝死关联的早期文献
6 Peng CK 等,心跳的长程反相关与非高斯行为,1993 长程相关分析
7 Mietus JE 等,pNNx 文件再审视,2002 HRV 指标的方法学批评
8 心衰 HRV 分析标准化评估综述 长短窗结论不一致的证据

附录 D:任务代码

#-- 端到端最小流程:取数、质控、算指标、分时段
import numpy as np
import wfdb

def load_rr(db, rec, ann_ext):
    hdr = wfdb.rdheader(rec, pn_dir=db)
    ann = wfdb.rdann(rec, ann_ext, pn_dir=db)
    rr = np.diff(ann.sample) / hdr.fs
    return rr[(rr > 0.3) & (rr < 2.0)]

def sdnn(rr):
    return float(np.std(rr, ddof=1) * 1000)

def rmssd(rr):
    return float(np.sqrt(np.mean(np.diff(rr) ** 2)) * 1000)

rr_chf = load_rr("chfdb", "chf01", "ecg")
print("心衰  SDNN", round(sdnn(rr_chf), 1), "RMSSD", round(rmssd(rr_chf), 1))

#-- 夜间段粗略定义为记录后三分之一
n = len(rr_chf)
night = rr_chf[2 * n // 3:]
print("末段  SDNN", round(sdnn(night), 1), "RMSSD", round(rmssd(night), 1))

这段代码把前文分散的步骤串起来,可直接运行。它刻意用了最少的依赖,以便在任何有网络的环境里复现。若要加入对照,按 §5.6 的方式加载 nsrdb 即可。

附录 E:如果只记五件事

序 要点
1 15 例 NYHA III–IV 级患者,每人约 20 小时双导联 250 Hz 心电,ODC-By 1.0 开放
2 它证明的是「心衰患者 HRV 低」这一关联,不是机制
3 标注自动生成未校正,用前必须做异位搏动与伪差处理
4 治疗背景停留在 1980 年代,β 阻滞剂缺席,基线不可直接搬到今天
5 它的价值在方法学与教学,不在临床建模

编辑说明

本页由千方病案医学编辑部整理,核查时间为 2026 年 10 月 27 日。核查方式是逐个访问 PhysioNet 的两个条目页面、文件目录、RECORDS 清单与若干头文件原文,并读取一篇论文摘要;没有下载全量波形做二次统计,也没有逐搏复核标注。凡本文未给出来源的判断,均为编辑团队基于上述材料所做的推断,已在文中标注。

文中关于「HRV 高低不能反推机制」的表述,属于对现有文献的综述性判断,不代表任何单一研究的结论。关于治疗年代差异的讨论,参考的是当代心衰指南的一般共识,不针对具体药物做疗效评价。

本页不与任何厂商存在利益关系。数据许可为 ODC-By 1.0,转载本页文字请遵循千方医数集的通用条款,转载数据请遵循 ODC-By 1.0 的署名要求。


相关数据集导航

以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:

  • wctecgdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ahadb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • crisdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • cudb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ltdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ltstdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • svdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • mhd-effect-ecg-mri — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • vfdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • physiozoo — 共享标签:生理信号 / 心电信号 / 心血管疾病

导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

返回 AI-Ready 数据集