都柏林一夜二十五人 — UCD 睡眠呼吸暂停库

25 人 / 14 路 EDF / 事件与分期同源

来源 https://physionet.org/content/ucddb/1.0.0/发布时间: 2026-10-28最后更新: 2026-10-28 阅读 10
都柏林一夜二十五人 — UCD 睡眠呼吸暂停库

信息速览

数据集名称都柏林一夜二十五人 — UCD 睡眠呼吸暂停库
数据类型时序信号,波形,人工标注,元数据
规模25 名受试者 / 25 段整夜记录
接入方式https://physionet.org/content/ucddb/1.0.0/
AI 就绪度

夜里十一点,都柏林南郊一家医院的睡眠实验室里,技师把一整套电极贴到受试者身上。头皮上两处,眼外各一处,下巴一处,胸口一处心电,鼻子下面一根热敏丝,胸腹各绑一条应变带,指尖夹一只血氧探头,喉头贴一只麦克风,床垫旁再放一台小盒子并行记录三导心电。

第二天早上,同一位技师把这些资料翻一遍。脑电、眼电与肌电先被切成三十秒一格,每格落一个整数;呼吸上的每一次变浅与停止则被抄成一行一行的文字,写着发生时刻、事件类型与持续秒数。这两份产物,一份是分期序列,一份是事件清单,从此各走各路。

UCD 在这里指 University College Dublin,即爱尔兰都柏林大学学院,不是美国那几所带 UC 字样的学校;"都柏林大学数据库"这个说法方向对,但漏掉了采集方是圣文森特大学医院。这个库是站内少数把整夜分期与呼吸事件分文件存放、且同时外挂一台 Holter 的睡眠库,本篇把它的全貌、文件结构、边界与用法逐层拆开,一屏速览见下表。

维度 内容
全名 St. Vincent’s University Hospital / University College Dublin Sleep Apnea Database
库名缩写 ucddb(UCD 指都柏林大学学院,非美国加州大学系统)
采集方 都柏林圣文森特大学医院睡眠障碍门诊
整理与提交 都柏林大学学院电气电子与机械工程学院,Conor Heneghan
首次发布 2007 年 10 月 9 日,版本 1.0.0
修订 2011 年 9 月 1 日发布修订版,波形重新上传
DOI 10.13026/C26C7D
受试者 25 名成人,21 男 4 女,年龄 28 至 68 岁
记录数 25 段,一人一段,编号 002 至 028 不连续
检查时长 单人 5.9 至 7.7 小时,合计约 173.2 小时
主波形 14 路 EDF,每数据记录一秒
外挂波形 Holter 三导心电,独立 EDF 文件
采样率与量化 官方页面未给采样率;EDF 规范本身为每样本 16 位
分期标准 Rechtschaffen 与 Kales,整数 0 至 5,另有 6 与 7
事件标注 独立文本清单,低通气、三类暂停、周期性呼吸
体积 未压缩 1.3 吉字节,ZIP 约 757 兆字节
许可 ODC-BY 1.0,免注册
缺什么 健康对照组、AASM 分期、Holter 与主机的对齐、逐秒事件标签

§1 它要解决的具体麻烦

1.1 一台多导仪与一台随身盒子并排记录

2002 年秋天到 2003 年春天,都柏林圣文森特大学医院的睡眠门诊在连续半年里接待了一批转诊者。诊断目的是三选一:阻塞型睡眠呼吸暂停、中枢型睡眠呼吸暂停,或者单纯打鼾。这些人被安排整夜监测,用的是德国 Erich Jaeger 公司的一套多导系统。

监测的同时,另有一台英国 Reynolds 公司的 Lifecard CF 记录仪贴在胸口,专门记三导心电。这不是多导仪自带的通道,而是一台可以带回家的 Holter 记录仪。两台设备并行的做法,决定了这个库后来最独特的一处结构:同一夜里存在两套波形文件,一套十四路、一套三路,分别落在两个文件里。

为什么要在睡眠监测里再加一台 Holter?官方页面没有交代动机,只写了这是同步记录。合理的读法是:多导仪那一路改良 V2 心电是为判读服务的,采样与导联位置按睡眠检查的惯例设置;而 Holter 三导是为更长时程的心律分析准备的,导联组合是 Holter 的常规配置。两者目的不同,所以没有合并成一路。

这个安排留下一个长期困扰:两套文件没有逐采样点对齐。官方明说录音时间不可得,Holter 与主波形之间只能靠时长与起始时刻去猜,§5 会专门处理。

1.2 三条常见的错误期待

第一条,期待 UCD 是美国加州大学戴维斯分校。 英文缩写撞车在这个库上格外常见。UCD 在睡眠文献里另有指代,搜索引擎也常把它和加州大学戴维斯分校的睡眠研究混在一起。真正的归属是爱尔兰,采集地在都柏林第四区的圣文森特大学医院,联系人是该校工程学院的 Conor Heneghan。这个误读会连带出第二个错误:把它当成美国人群的样本,从而在讨论人群代表性时得出方向相反的结论。

第二条,期待它是"患者与对照各半"的设计。 官方写受试者是从门诊转诊者中随机抽取的,转诊理由是"可能的阻塞型、中枢型呼吸暂停或单纯打鼾"。这句话容易被读成有健康对照组。实际上没有:所有入组者都是被怀疑有病才被送来的,只是一个严重程度谱很宽的疑似队列,其中少数人的呼吸暂停指数落在个位数,接近正常,但他们在设计上仍属于"被怀疑者",不属于健康志愿者。

第三条,期待分期文件里有时间戳。 _stage.txt 是一个纯文本文件,每行一个整数,没有时刻、没有受试者名、没有列名。它隐含的约定是"第一行对应记录开头,每行三十秒"。这个约定在官方页面上没有明写,只能从文件行数与记录时长去反推。任何把它当成带时间列的表格读入的脚本,都会在第一行就错位。

1.3 它能给到的与给不到的

你的需求 它给的 够不够
呼吸事件与睡眠期的配对观察 同一技师判读的分期与事件,时段对得上 够,两类标签同源
单夜十四路的完整生理切片 眼电、肌电、双导脑电、气流、胸腹带、血氧、鼾声、体位 够,通道覆盖接近临床全套
独立于多导仪的心电复核 Holter 三导,独立文件 够,但不能逐点对齐
呼吸暂停严重程度的分层 受试者表给出每人的呼吸暂停指数 够,可自行按阈值分组
按 AASM 五类做分期训练 只有 R&K 整数 0 至 5 不够,需先映射
逐秒的暂停起止标签 事件为行文本,只有时刻与总时长 不够
健康人与患者的对照 全部为疑似患者 不够,没有健康组
多导脑电的空间分析 只有中央区的两个导联 不够

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

你的处境 它能帮你什么 下一步该做什么
你在做呼吸事件检测,需要一个带事件清单的小样本对照 25 段均有事件行清单,含类型与时长 先按 §5.3 把清单解析成表,再与分期对齐
你在验证一个从单导心电推呼吸暂停的模型 有独立 Holter 三导,可做跨设备检验 先确认 Holter 与主机的时间偏移,再逐段对齐
你要做睡眠分期,但只有 R&K 标签 25 段全夜、双导脑电、双导眼电齐全 按 §4.3 把 4 与 5 合并成深睡后再训练
你在教学,要把一次检查讲完整 十四路通道与两份标注文件,链路清楚 用编号 002 的那一段做演示,它只采到两路心电,正好讲清设备差异
你需要一个女性样本做性别差异分析 只有 4 名女性 不够,换多中心队列
你要做端到端深度模型的主训练集 25 人单中心 不够,当外部验证集更合适

1.5 一句话判断

它是一个把"判读结果"而不是"判读过程"完整留了下来的整夜睡眠库:波形齐全,标签干净,但两者之间没有一步是被逐秒对上的。

1.6 不适合谁:四条边界

不适合拿它训练大模型。 25 名受试者、25 段记录、单中心单夜。这个体量在 2010 年代的分期研究里尚可作为独立训练集,放到今天只能是外部验证。把它当主训练集,模型学到的是这 25 个人的头皮阻抗与病房环境。

不适合拿它做性别差异研究。 4 名女性、21 名男性,任何按性别分组的统计都只有个位数的分母。官方没有公布按性别分层的任何指标,自己也回避了这个问题。

不适合拿它做多导脑电分析。 两路脑电都在中央区,C3-A2 与 C4-A1,是睡眠分期的标准配置,不是脑电研究的配置。没有额区、没有枕区、没有中线,做不了空间分布,也做不了源定位。

不适合把它当成 AASM 体系的数据。 分期体系是 R&K,事件判据也是那个年代的(官方只写类型与时长,没有写判据阈值)。与 2007 年之后的 AASM 库放在一起做准确率对比,比的是两套判据,不是两个模型。

§2 数据构成与规格

2.1 一个扁平目录、四件套与两份全局表

整个库在 PhysioNet 上是一个扁平的目录,没有子文件夹。25 段记录各占四个文件,另有三份全局文件:记录清单、校验和、受试者表。

文件 后缀 大小量级 作用 能否省
主波形 .rec 26 至 40 兆字节 14 路 EDF 波形 不能
Holter 波形 _lifecard.edf 20 至 23 兆字节 3 路心电 EDF 做心电时必需
睡眠分期 _stage.txt 约 2.1 至 2.7 千字节 每行一个整数 不能
呼吸事件 _respevt.txt 0.9 至 33.4 千字节 定宽文本行清单 做事件时必需
记录清单 RECORDS 875 字节 五十行,主波形与 Holter 交替 不能,是遍历入口
校验和 SHA256SUMS.txt 8.3 千字节 全库文件摘要 建议留
受试者表 SubjectDetails.xls 11 千字节 25 行人口学与检查摘要 不能,唯一的结构化元信息

这里要提前点明:RECORDS 有五十行,不是二十五行。它交替列出主波形与 Holter 两个文件名,行数是记录数的两倍。若把每一行当成一次记录,会得到五十"条"的错觉,且每条只有半套文件。

2.2 字段与记录的完整字典

受试者表是本库唯一的结构化元信息表。它是一张 25 行、14 列的电子表格,前若干列是人口学,后几列是检查摘要。表头英文,无单位说明,靠列名自行理解。

列 含义 单位 取值形态 注意
S/No 表内行号 无 1 至 25 与文件名编号不一致
Study Number 记录编号 无 UCDDB002 至 UCDDB028 字母大写,与文件名小写不同
Height 身高 厘米 整数 无缺失
Weight 体重 千克 一位小数 无缺失
Gender 性别 无 M 或 F 21 人 M,4 人 F
PSG Start Time 检查起始时刻 时:分:秒 多为 22 至 24 时 有 0 时与 23 时两种跨零点写法
PSG AHI 呼吸暂停低通气指数 次每小时 整数 官方摘要口径为均值与范围
BMI 体质指数 千克每平方米 一位小数 由身高体重算出,个别行有尾差
Age 年龄 岁 整数 28 至 68 岁
Epworth Sleepiness Score 日间嗜睡量表分 分 整数 官方正文未提,仅表中存在
Study Duration (hr) 检查时长 小时 一位小数 5.9 至 7.7 小时
Sleep Efficiency (%) 睡眠效率 百分比 整数 官方正文未提,仅表中存在
无名列 空列 无 全空 表结构残留
No of data blocks in EDF EDF 数据记录数 个 整数 约为 _stage.txt 行数的三十倍

最后一列是个有用的交叉验证点:EDF 的数据记录个数等于分期文件的行数。这说明主波形的 EDF 一个数据记录恰好一秒,而分期一行恰好三十秒,等一下——两者数字相等,意味着分期行数其实与秒数对齐记数,而非与三十秒格数对齐。核对时要看具体记录,不能想当然。

分期文件的编码在官方页面上给了一张对照表,只有八行。

整数 官方释义 常规 R&K 记号 备注
0 Wake,清醒 W 整数 0 而非字母
1 REM,快速眼动 R 与"一期"不同,易混
2 Stage 1,一期 1
3 Stage 2,二期 2
4 Stage 3,三期 3 慢波睡眠前半
5 Stage 4,四期 4 慢波睡眠后半
6 Artifact,伪迹 无对应 非常规类别
7 Indeterminate,不确定 无对应 非常规类别

这张表最容易被读错的地方是前两行:0 是清醒,1 是快速眼动。很多库里 1 代表一期,这里不是。数字与期号之间有整体错位:一期是 2,二期是 3,三期是 4,四期是 5。任何一个按"数字即期号"写映射的脚本,都会把全部类别整体挪一格。

呼吸事件文件是另一种形态。它有三行表头,之后每行一次事件,按定宽列对齐,列与列之间靠空格分隔,缺值留空。

列位 表头 含义 取值形态
1 Time 事件发生时刻 时:分:秒
2 Respiratory Event Type 事件类型 HYP-O、HYP-C、APNEA-O、APNEA-C、APNEA-M
3 PB/CS 周期性呼吸或潮式呼吸标记 PB、CS 或空
4 Duration 事件持续秒数 整数
5 Desaturation Low 事件中最低血氧 百分比
6 %Drop 血氧相对下降幅度 百分比
7 Snore 鼾声标记 - 或 +
8 Arousal 觉醒标记 - 或 +
9 B/T Rate 心动过缓或过速时的心率 次每分钟,常空
10 B/T Change 心率的相对变化 百分比,常空

第 7 与第 8 列用正负号而非真假值,第 9 与第 10 列则在很多行里整体留空。这不是数据损坏,而是"本次事件没有对应的数据块时留空"的写法。解析时若按列位硬切,空列会导致后列整体左移,必须按表头给出的列宽处理,或者用正则按固定位置切。

2.3 一条记录的完整解剖

把编号 002 的那一段从头拆一遍,能看到这批数据的组织方式。它是全库第一条,也是官方专门提过一句的那一条。

#-- 逐层解剖一段:主波形、Holter、分期、事件
from pathlib import Path

base = Path("ucddb")
for f in sorted(base.glob("ucddb002*")):
    print(f.name, f.stat().st_size)
#-- 分期是纯整数文本,行号即时间序
st = [int(x) for x in (base / "ucddb002_stage.txt").read_text().split()]
print("格数", len(st), "前五格", st[:5])
#-- 事件文件前三行是表头,之后才是行
lines = (base / "ucddb002_respevt.txt").read_text().splitlines()
print("表头行", lines[0].strip())
print("首条事件", lines[3])

跑完会看到四个文件的体积关系:主波形约 27 兆,Holter 约 20 兆,分期只有 2.2 千字节,事件 9.7 千字节。四个数量级的差别正好对应信息的稠密程度:波形是逐秒的数百万个采样点,标注只是几百个数与几十行字。

再看分期文件的内部。它没有时间列,第一行对应记录起点。官方没有写清第一格是否与波形的第一个采样点对齐,也没有写明记录末尾不满三十秒的那一截如何处理。能确认的只有一件事:分期行数约等于数据记录数的三十分之一,与每行三十秒的约定吻合,可用来校验配对。编号 002 的行数为七百四十八,记录数除以三十取整为七百四十九,差的那一行正是末尾不满一格的一截。

解剖层级 内容 数量级 备注
库 25 段记录 25 扁平存放,无子目录
记录 一名受试者的一夜 约 6 至 8 小时 编号不连续
文件 四件套 4 两份波形两份标注
主波形通道 14 路 14 头部有拼写错误,见 §3.4
Holter 通道 3 路 3 仅标 chan 1 至 3
记录节拍 每数据记录一秒 整夜千余至两千余记录 头部声明,逐路采样率官方未给
分期格 三十秒一格 时长除以三十 整数编码
事件行 一次呼吸事件 每段数十行 定宽文本

2.4 二十五段记录的规模与结构

受试者表把 25 段的规模一次交代清楚。下表只取结构性字段,不列逐人明细。

记录 性别 检查时长(小时) EDF 数据记录数 备注
ucddb002 男 6.2 22470 仅两路不同心电,第三路为复制
ucddb003 男 7.3 26478
ucddb005 男 6.9 24798
ucddb006 男 6.7 24267
ucddb007 男 6.8 24405
ucddb008 女 6.4 23041
ucddb009 男 7.7 27759 全库最长
ucddb010 男 7.6 27211
ucddb011 男 7.5 27030
ucddb012 男 7.2 25941
ucddb013 女 6.8 24333
ucddb014 男 6.4 23239
ucddb015 男 7.6 27488
ucddb017 男 6.6 23684
ucddb018 男 6.8 24685
ucddb019 男 7.1 25573
ucddb020 男 6.3 22586
ucddb021 女 7.6 27409
ucddb022 男 6.6 23640
ucddb023 女 7.2 25850
ucddb024 男 7.6 27250
ucddb025 男 5.9 21350 全库最短
ucddb026 男 7.0 25160
ucddb027 男 7.4 26791
ucddb028 男 6.0 21660

三条结构规律可以从中读出。第一,编号缺 004 与 016,说明这批记录来自一个更大的编号池,只是两个编号没进最终版本;官方没有解释缺号原因。第二,时长集中在六到七小时以上,最短 5.9 小时、最长 7.7 小时,全部短于一个完整的自然夜,这与"病历记录时长只算监测期间"的做法一致。第三,数据记录数与检查小时数的比值恒在每秒一个记录的量级(头内声明每记录一秒),说明 14 路共用同一个记录节拍,没有哪一路被单独抽成独立节拍。

2.5 与同类资源的字段差异

把本库放进睡眠类资源里横向比,最显眼的位置是"通道中等、标注分文件、带外挂心电"。

字段维度 本库 大型公开 PSG 基准 可穿戴睡眠库 电子病历型睡眠队列
受试者规模 25 数十至两百 数十至数千 数千至上万
记录长度 约 6 至 8 小时 整夜或多夜 多夜连续 一至多夜
脑电通道 2 2 至 6 0 至 2 2 至 6
呼吸通道 气流、胸带、腹带三路 多为两路 无 多为两至三路
外挂心电 三导 Holter 通常无 无 无
分期体系 R&K AASM 为主 多为 AASM AASM 为主
标注存放 分期与事件各一文件 单一标注文件 单一标签列 数据库表
许可 ODC-BY 免注册 多为免注册 各异 多为申请制

它的信息密度集中在两列:呼吸三路齐全,以及那套外挂 Holter。这两样决定了它的独特用途。规模与分期标准两列则全面落后,是三十年前后两个时代的正常差距。

§3 它从哪里来:一家爱尔兰医院与一位工程师

3.1 采集在医院,整理在学校

这个库的署名结构有两层,对应两个机构。采集发生在医院:圣文森特大学医院睡眠障碍门诊,由 Walter McNicholas 教授主持。整理与提交在学校:都柏林大学学院电气电子与机械工程学院,联系人是 Conor Heneghan 博士。

官方页面把贡献者一一列出,每个人的分工也写得具体。这种写法在 PhysioNet 老库里罕见,值得照抄下来。

角色 姓名或单位 承担的工作 出处
采集主持 Walter McNicholas 教授 睡眠门诊的监测与临床判读把关 官方致谢
临床与人口学信息 Liam Doherty、Silke Ryan、John Garvey 收集并整理临床与人口学资料 官方致谢
分期与事件判读 Patricia Boyle 全部记录的睡眠分期与呼吸事件标注 官方致谢
去标识与归档 Eric Chua 记录脱敏与电子归档 官方致谢
提交联系人 Conor Heneghan 向 PhysioNet 提交并维护 官方联系信息
托管 PhysioNet 版本发布与长期保存 官方页面

最有价值的是判读那一行:全库的分期与事件由同一人完成,两类标签的判读习惯连贯,不会出现分期与事件各按一人习惯的错位。代价是没有第二位判读人,无法估一致性。

3.2 入选条件写得比多数库都清楚

官方摘要的受试者一段,把纳入标准逐条列出了。这些条件本身就是这个库的边界:

  • 年龄大于十八岁
  • 已知无心脏病
  • 无自主神经功能障碍
  • 未服用已知会干扰心率的药物
  • 转诊理由为可能的阻塞型、中枢型睡眠呼吸暂停或单纯打鼾
  • 从连续半年的转诊者中随机抽取

前三条合在一起,勾勒出的是一个"心血管相对干净"的人群。这正是为了配合那台 Holter:要研究呼吸事件对心率的即时影响,就得排除心脏本身的病变与药物干扰。所以这个库在设计上是一个呼吸与心率耦合研究的样本,睡眠监测只是采集手段。

第二到第四条也解释了为什么样本里几乎没有重症心肺共病者,而这类共病在真实睡眠门诊里并不少见。使用者若把它当成"睡眠门诊人群"的代表,会系统性低估共病比例。

纳入条件 排除了什么 对使用者的含义
大于十八岁 儿童与青少年 不能外推到儿科
无已知心脏病 心衰、房颤、冠心病 心率变异分析无病理混杂
无自主神经功能障碍 糖尿病神经病变等 自主神经指标更"干净",也更不真实
未用干扰心率的药 β 受体阻滞剂等 心率反应可在无药物背景下解读
疑似呼吸障碍 健康志愿者 无健康对照
连续半年随机抽取 季节性偏倚被部分控制 单中心偏倚仍在

3.3 时间线

时间 事件 依据
2002 年 9 月至 2003 年 2 月 转诊者陆续入组,监测跨这半年 官方摘要
2003 年 7 月至 12 月 分期文件定稿 文件修改时间
2003 年 7 月至 2004 年 1 月 事件文件陆续定稿 文件修改时间
2006 年 10 月 分期文件集中重写一遍 文件修改时间
2007 年 10 月 9 日 PhysioNet 发布 1.0.0 官方页面
2011 年 9 月 1 日 修订版发布,波形与受试者表重新上传 官方摘要与文件修改时间
2019 年 2 月 补录校验和清单 文件修改时间

两条细节值得记。第一,分期文件比波形晚了好几年才定稿,说明标注是在监测结束之后集中做的,不是当晚同步写的。第二,2011 年的修订版把波形重新上传了一次,但版本号仍写 1.0.0;若在 2010 年之前下载过,文件内容未必与今天一致。

3.4 采集现场:十四路与一个拼写错误

官方把信号清单逐项列出,但没有给设备参数表。能从文件本身读出的只有头部信息。这里有一处细节很适合作为"读原始文件"的教训。

主波形文件其实是 EDF 格式,但通道名不是 EDF 标准的 16 字符对齐字段,而是各自灵活排列的短名。逐段读下来,14 路的通道名依次是:左眼电、右眼电、下颌肌电、C3-A2、C4-A1、心电、血氧、鼾声、口鼻气流、胸腹带合计、胸带、腹带、体位、脉率。

其中第 8 路的通道名,在编号 003 的文件里写成了 Soud,在编号 002 的文件里写成 Sound。同一批数据里同一路信号有两种拼写。这不是孤例:EDF 头里还有一处日期字段被统一写成 2001 年 1 月 1 日,与实际采集年份 2003 年不符。

采集要素 官方描述 文件中的表现 需要注意
脑电 C3-A2 与 C4-A1 通道名写成 C3A2、C4A1 少一个连字符
眼电 左眼、右眼 Lefteye、RightEye 双导齐全,可做眼动判读
肌电 下颌 EMG 无胫骨前肌,腿部运动无法核实
心电 改良 V2 ECG 与 Holter 三导不是同一套
气流 口鼻热敏 Flow,单位升每分钟 热敏信号对低通气灵敏度有限
呼吸带 胸、腹、合计 ribcage、abdo、Sum 官方称应变带未标定
血氧 指夹 SpO2,百分比 事件表里的最低血氧应与此对应
鼾声 气管麦克风 Sound 或 Soud 拼写随记录变化
体位 传感器 BodyPos 官方未说明编码含义
脉率 未单列 Pulse,次每分钟 与 Holter 心率可互相校验

"未标定"这个词出现在官方对胸腹带的描述里。它的意思是呼吸带的幅值只有相对意义,不能直接换算成容积。做呼吸努力分析可以,做潮气量估计不行。这一点在 §7 会再提。

3.5 两个口径:头部字段与文件体积

官方页面只写了"以 EDF 格式存放",没有给采样率与量化位数。要拿到这两个数只能读头部,而头部有两处需要说清。

第一处是头部字段与文件体积之间对不上。以编号 002 为例,头里写着每个数据记录占三千八百四十字节、共两万二千四百七十个记录、每记录一秒;三项相乘应得八十余兆,而文件本身只有二十七点四兆。差额约三倍,官方没有说明原因。

口径 数值 来源 与什么一致
每数据记录字节数 3840 头部字段 与头部尺寸自洽(头部正好等于一个记录)
数据记录数 22470 头部字段与受试者表 与检查时长自洽
每记录时长 1 秒 头部字段 与记录数除以时长自洽
三项相乘的体积 约 86 兆 上面三行推算 与文件体积不符
文件实际体积 27.4 兆 页面文件清单与下载结果 与上一行不符
采样率 官方未给 官方页面 无法从头部单方确定

第二处是日期。EDF 规范要求写明起始日期,本库统一填成 2001 年 1 月 1 日,而受试者表与事件文件都指向 2003 年,这个值只能当作占位符。

两处指向同一个结论:这批文件是设备导出的 EDF 变体,字段并非严格按规范填写。读的时候要靠头部、文件体积与外部表格三方交叉,单看任何一方都会得出错误结论。§4.4 的案例会把这个交叉过程走一遍。

§4 它最独特的东西:一次判读、两份文件

4.1 标注被拆成了两套文件

多数睡眠库把分期与事件写进同一个注释文件,用不同符号区分。本库不这么做:分期是 _stage.txt 里的整数序列,事件是 _respevt.txt 里的表格。两者物理分离,结构完全不同。

这个选择有好处也有代价。好处是两者都能被最笨的工具读进来:一个纯文本整数列,一张定宽文本表,连专门的信号库都不需要。代价是两者的时间轴需要自己缝合:分期是相对记录起点的格序号,事件是绝对的时刻字符串,两者之间的换算要靠起始时刻做中介。

对比项 分期文件 事件文件
格式 单列整数 带表头的定宽文本
粒度 每行代表一段睡眠期 每行代表一次呼吸事件
时间表示 无,靠行序 时:分:秒
类别数 8 个整数 5 类事件加两个气道标记
一行的信息量 一个类别 十个字段
解析难度 极低 中等,需处理缺列
与另一方对齐 靠格序号乘三十秒 靠时刻减去起始时刻

4.2 事件类型只有五种,但每种的判据没写

官方列出的事件类型是:低通气(HYP)、中枢型暂停(C)。

更准确地说,文件里的第二列用的是复合写法:HYP-O 表示阻塞型低通气,HYP-C 表示中枢型低通气,APNEA-O 表示阻塞型暂停,APNEA-C 表示中枢型暂停,APNEA-M 表示混合型暂停。也就是说低通气也分了气道类型,这比很多库做得细。

第二列取值 中文 类别 备注
HYP-O 阻塞型低通气 低通气 气流下降但未完全停止
HYP-C 中枢型低通气 低通气 中枢驱动的减弱
APNEA-O 阻塞型暂停 暂停 气道塌陷
APNEA-C 中枢型暂停 暂停 无呼吸驱动
APNEA-M 混合型暂停 暂停 中枢起始、阻塞收尾
PB 周期性呼吸 事件标记 出现在第三列
CS 潮式呼吸 事件标记 出现在第三列

第三列是独立的气道模式标记,不是事件类型。它出现时,同一行的第二列仍有事件类型。这一点在解析时容易被忽略:把第三列的 PB 当成事件类型统计,会与第二列的计数混在一起。

4.3 分期体系:R&K 与它留下的两个尾巴

官方写的是按 Rechtschaffen 与 Kales 规则判读,由一名资深技师完成。这在 2002 年完全合规——AASM 新版手册要到 2007 年才成为主流。所以本库用的是当时的临床标准,不是过时标准。

真正需要留意的是两个非标准的尾巴:6 与 7。R&K 体系本身只有六类(W、1、2、3、4、R),不存在"伪迹"与"不确定"这两个期。本库把它们单独编码,说明判读员在遇到无法归类的格子时,选择了标记而不是硬塞进某一期。

本库编码 本库含义 R&K 原始记号 AASM 对应 映射是否唯一
0 清醒 W W 是
1 快速眼动 R R 是
2 一期 1 N1 大致是,边界判据不同
3 二期 2 N2 大致是,纺锤与 K 复合波规则有别
4 三期 3 N3 否,需与 5 合并
5 四期 4 N3 否,需与 4 合并
6 伪迹 无 无 只能剔除
7 不确定 无 无 只能剔除

映射在 4 与 5 两行不唯一,这是 R&K 与 AASM 的结构性差异,任何跨库比较都绕不开。6 与 7 两行更麻烦:它们不是睡眠期,做多分类时必须先剔除或单列一类,否则类别数与官方给的六个主符号对不上。

这里还有一处口径值得并列:官方在同一张表里把 1 写成 REM,这与前文提到的"1 不是一期"完全一致。但因为多数库用 1 表示浅睡,读到这里的直觉反应往往是"官方写错了"。不是写错,这是本库自己的编号约定。

4.4 案例:ucddb002 的两路心电与三处错位

拿编号 002 的那一段走一遍,能把这批数据的几处特点一次看清。它既是全库第一条,也是官方在摘要里唯一点名的一条,理由就写在那句话里:这一段只采到两路不同的心电,第三路是把第二路复制过来的。

先看文件层面。这一段的四个文件都在,主波形 27.4 兆,Holter 20.2 兆,分期 2.2 千字节,事件 9.7 千字节。分期文件以整数 0 开头,符合"检查从清醒开始"的常理。

再看三处错位。

第一处,通道名的拼写。 这一段第 8 路写作 Sound,而编号 003 的同一路写作 Soud。按名取通道的代码在这两段上会得到不同结果,必须按位置取或做模糊匹配。

第二处,Holter 的通道名。 打开 ucddb002_lifecard.edf,三路通道名统一写作 chan 1、chan 2、chan 3。官方摘要说这三路是 V5、CC5、V5R,但文件里没有任何一对一的对应关系。要知道哪一路是哪一导,只能靠波形形态去猜。

第三处,Holter 的帧数比主机多。 主波形这一段的头文件声明 22470 个数据记录,Holter 文件声明 27540 个数据记录。两者相差五千余帧。官方明说录音时间不可得,所以这五千余帧究竟是起始处的额外录制、末尾的延后,还是两者兼有,无法从文件本身判定。

§4.4 的案例说明了一件事:这个库的文件结构是"看起来齐整、细看处处需要交叉验证"的类型。它把该给的信息都给了,但给的方式是分散在三个文件与一张外部表格里。

这三处里,最影响使用的其实是第三处。做呼吸事件与心率的时序对齐时,若默认两套文件起点相同,误差会随着夜渐而累积。稳妥的做法是先在 Holter 上找几个明显的心率骤升点,再在主波形心电上找同样的点,用它们估出偏移量,而不是相信起始时刻。

§4.4 的案例还有一处补充。它的受试者表里有日间嗜睡量表分与睡眠效率两列,而官方正文对这两列只字未提。也就是说,这两列是随表一起给出的"顺手产物",官方没有把它们当作正式变量。用它做分析可以,但引用时要说明来源是表而非正文。

4.5 边界条件:什么情况下它不再适用

五种情况下这批数据会失效,失效方式各不相同。

第一种,任务从"疑似患者"扩到"一般人群"。 全部受试者都因被怀疑有病才被送来做检查,没有健康志愿者。要估计正常人群的睡眠结构分布,这里没有基准。

第二种,需要严格的时间对齐。 主波形与 Holter 之间、分期与波形之间,都存在未说明的对齐问题。要研究秒级的心电—呼吸相位关系,先得自己估偏移。

第三种,需要逐秒的事件标签。 事件只有起始时刻与总时长,中间过程没有标注。要训练逐秒的事件检测器,标签得自己造。

第四种,需要现代分期标准。 R&K 的 4 与 5 要合并,6 与 7 要剔除,映射后的类别与 AASM 库仍不完全等同。

第五种,需要性别或年龄分层的结论。 4 名女性、跨度 28 到 68 岁,任何分层都只有个位数样本。

§5 怎么拿到:从记录清单到事件表

5.1 目录结构与下载面

官方给三条路:页面的 ZIP 按钮、wget 递归、AWS 开放桶同步。目录扁平,脚本遍历很直接:读 RECORDS 得到五十行,每行是 .rec 或 .edf 文件,去掉扩展名就是主干名的一支。

下载方式 命令要点 适合场景 注意
ZIP 页面按钮 一次性拿全量 约 757 兆,解压后 1.3 吉
wget 递归 加 -r -N -c -np 需要断点续传 会连目录索引一起拉
AWS 同步 s3 sync --no-sign-request 批量、可并行 需装命令行工具
逐文件 按主干名拼 URL 只取几段做实验 最省流量,适合教学

对一个一点三吉的库,四条路的差别主要在续传与并行。真正值得挑的是第四条:做教学演示取两段就够,做跨记录分析才需要全量。

5.2 批量下载

#-- 先取清单与受试者表,再按主干名拉四件套
BASE="https://physionet.org/files/ucddb/1.0.0"
mkdir -p ucddb && cd ucddb
curl -sSL -O "$BASE/RECORDS"
curl -sSL -O "$BASE/SHA256SUMS.txt"
curl -sSL -O "$BASE/SubjectDetails.xls"
#-- 清单每两行一组,取奇数行即为记录主干
awk 'NR%2==1 {sub(/\.rec$/, ""); print}' RECORDS > stems.txt
wc -l stems.txt
#-- 按主干名补四件套
while read -r s; do
  for suffix in ".rec" "_lifecard.edf" "_stage.txt" "_respevt.txt"; do
    f="$s$suffix"
    [ -s "$f" ] || curl -sSL --retry 3 -o "$f" "$BASE/$f"
  done
done < stems.txt
ls *_stage.txt | wc -l

awk 'NR%2==1' 按清单的交替规律取主波形行,避免自己拼编号时漏掉缺号。最后一行输出应为 25。若某个文件只有几百字节,多半是中断留下的残片,删掉重下。

#-- 校验完整性
sha256sum -c SHA256SUMS.txt --quiet || echo "有文件校验失败"

5.3 读波形与解析两份标注

读进来之后第一件事不是滤波,是确认通道名、帧数与标注行数三者能否对上。

#-- 读主波形与 Holter 的头,核对通道与帧数
import mne

raw = mne.io.read_raw_edf("ucddb/ucddb002.rec", preload=False, verbose=False)
print("通道数", len(raw.ch_names))
print("采样率", raw.info["sfreq"])
print("时长小时", round(raw.n_times / raw.info["sfreq"] / 3600, 2))
print(raw.ch_names)
hol = mne.io.read_raw_edf("ucddb/ucddb002_lifecard.edf",
                          preload=False, verbose=False)
print("Holter 通道", hol.ch_names, "采样率", hol.info["sfreq"])

主波形应读出 14 路,Holter 应读出 3 路且通道名为 chan 1 至 chan 3。两边的时长若不一致,就是 §4.4 的案例里说的那一处偏差。

第二步是把分期序列还原成带时间的列表,并把事件解析成结构化表。

#-- 分期:行序乘三十秒即时间轴
from pathlib import Path

raw_st = [int(x) for x in Path("ucddb/ucddb002_stage.txt").read_text().split()]
ruler = [(i * 30, i * 30 + 30, v) for i, v in enumerate(raw_st)]
print("首格", ruler[0], "末格", ruler[-1])
#-- 事件:前三行为表头,之后按列位切
import re
rows = []
for ln in Path("ucddb/ucddb002_respevt.txt").read_text().splitlines()[3:]:
    m = re.match(r"(\d{2}:\d{2}:\d{2})\s+(\S+)\s+(\S*)\s+(\d+)", ln)
    if m:
        rows.append((m.group(1), m.group(2), m.group(4)))
print("事件条数", len(rows), "首条", rows[0])

这里只取前四列,因为后六列存在整列留空的情况。要做血氧分析,需要单独用列位切片,不能靠空格分列。

5.4 换到常见工具链

不是所有工具链都吃 EDF 的非规范变体。MNE 能读,但会按头里的位宽声明去缩放,读出的幅值可能与原值差一个因子。稳妥的做法是先读入、再与头里的物理单位做一次合理性检查。

#-- 用 EDFbrowser 的命令行版本抽一段出来看
edfbrowser ucddb003.rec -start 18000 -duration 60 -channel 6 -output ecg_1min.txt
#-- 输出为两列:时间与幅值,可用于快速目视核对
head -3 ecg_1min.txt

若手上没有 EDFbrowser,用 Python 直接切也可以:按通道索引取第 6 路(心电)第 18000 秒起的一分钟,画出来看波形形态是否像心电。这一步很土,但能在半小时内判断整批文件的位宽问题是否会影响结论。

批量读 25 段时会遇到内存问题:14 路乘以整夜数小时,单段解包后可达数百兆。稳妥的做法是只读需要的通道,或者按分钟分块处理。

#-- 只读心电与气流两路,逐段汇总结构信息
import mne, re
from pathlib import Path

rows = []
for p in sorted(Path("ucddb").glob("ucddb0*.rec")):
    r = mne.io.read_raw_edf(p, preload=False, verbose=False)
    keep = [c for c in r.ch_names if re.match(r"(ECG|Flow)$", c.strip())]
    rows.append((p.stem, len(r.ch_names), round(r.n_times / r.info["sfreq"] / 3600, 2), keep))
for r in rows:
    print(r)

输出应显示每段 14 路、时长在六到八小时之间、两路目标通道都能取到。若某段取不到 ECG,先检查大小写与空格,通道名在文件里可能带尾随空格。

5.5 一个容易踩的坑:编号不连续

编号从 002 到 028,缺 004 与 016。按 range(2, 29) 循环会在两处抛异常,按"共 25 个"去拼字符串会全部错位。

#-- 用受试者表做主键,而不是自己拼编号
import pandas as pd

sd = pd.read_excel("ucddb/SubjectDetails.xls")
ids = [s.lower().replace("ucddb", "ucddb") for s in sd["Study Number"]]
print("记录数", len(ids), "首末", ids[0], ids[-1])
missing = [f"ucddb{i:03d}" for i in range(2, 29) if f"ucddb{i:03d}" not in ids]
print("缺号", missing)

输出的缺号应是 004 与 016。以受试者表为唯一事实来源,可以避开所有手工拼编号的问题,也能顺带把性别与时长一起带进来。

5.6 五个最容易出错的地方

出错点 表现 原因 处理
按"数字即期号"映射 全部类别整体挪一格 0 是清醒、1 是 REM 按 §2.2 的对照表硬编码
假定两套波形起点相同 夜间后半段心率对不齐 Holter 帧数更多、时间不可得 先用心率突变点估偏移
按空格分列事件 后六列整体左移 空列不留占位 按定宽位置切或用正则
按编号区间循环 缺 004 与 016 时报错 编号不连续 以受试者表为主键
按格随机划分训练测试 跨人准确率虚高 一人一段但同一晚内格高度相关 以人为单位划分

最后一条需要多说一句。本库一人一段,没有 slpdb 那种同一人两段的情况,所以不存在跨段泄漏。但同一夜内相邻的三十秒格高度相关,按格随机切仍会让相邻格落在训练与测试两侧,得到虚高的成绩。正确做法是按人留一,或者按夜分块切。

§6 与库内条目的关系

6.1 关系图谱

站内与睡眠有关的记录已经很多,彼此的分工需要先划清。与本库最容易被混同的,是同样按老标准标注的 slpdb,以及三个常被拿来做对照的现代库:sleep-accel、sleep-edf 系与 cps-dataset-sleep。

库内记录 与本库的关系 人群 通道与设备 呼吸事件标注 分期体系
slpdb 同为 PhysioNet 老库,同用 R&K 16 名男性,全部 OSA 评估者 4 至 7 路 WFDB,单导脑电,含有创血压 有,合并符号 R&K 五期,符号为 W 与数字
本库 — 25 名男女混合的疑似患者 14 路 EDF 加独立 3 路 Holter 有,独立行清单 R&K 五期,整数 0 至 5
sleep-accel 同做睡眠分期,但走腕表 31 人 腕部加速度计,单路 无 AASM,由家用设备推算
sleep-edf 同用 EDF 与双导脑电 健康志愿者与睡眠障碍者 2 路脑电为主的 PSG 基本没有 AASM 为主
cps-dataset-sleep 同来自临床诊断场景 成人与儿童综合队列 数十路现代 PSG 有,多类细标签 AASM

四条区隔可以逐条落地。

与 slpdb 的区隔最需要说清。 两者同属 PhysioNet 早期托管的老库,同按 R&K 分期,容易被当成同一批数据的不同版本。实际上除了标准相同,几乎处处不同:slpdb 采集于 1989 至 1990 年的波士顿,全部男性;本库采集于 2002 至 2003 年的都柏林,男女混合。slpdb 用 WFDB 三件套存放,脑电只有单导,最稀有的是连续有创动脉压与部分记录的心输出量;本库用 EDF,脑电两导,呼吸通道三路齐全,最稀有的是一台独立的三导 Holter。口径也不同:slpdb 的分期符号是字母 W 加数字 1 至 4,本库是纯整数 0 至 5 且 0 为清醒、1 为快速眼动。

对照项 slpdb 本库
采集地 波士顿,贝斯以色列医院 都柏林,圣文森特大学医院
采集年份 1989 至 1990 2002 至 2003
受试者 16 名男性 25 名,21 男 4 女
记录数 18 段,两人各两段 25 段,一人一段
文件格式 WFDB 头、波形、注释三件套 EDF 波形加两份文本标注
脑电 单导,导联随记录变化 双导,C3-A2 与 C4-A1
特有信号 有创动脉压、部分心输出量 独立三导 Holter
事件标注 与分期同处一份注释 独立行清单,含血氧与脉率变化
分期符号 字母加数字 纯整数,0 为清醒、1 为 REM
体积 约 632 兆 未压缩 1.3 吉

与 sleep-accel 的区隔在设备。 那个库只有腕部加速度一路,分期由家用设备推算,没有呼吸事件,也没有任何生理通道。本库是实验室级的多导配置。两者唯一的重叠是"都做分期",但一个是临床金标准的判读结果,一个是消费级设备的输出,用途上不构成替代关系。

与 sleep-edf 系的区隔在通道与标注。 那一族以双导脑电为主,按 AASM 或旧版判读,几乎没有呼吸事件标签,人群以健康志愿者与睡眠障碍者混合。本库的呼吸事件是其核心资产之一,而 sleep-edf 系的价值在于分期基准的规模与标准化。

与 cps-dataset-sleep 的区隔在年代与粒度。 那个库来自现代临床设备,通道数多、事件类别细、分期按 AASM,访问需协议。本库年代早、通道中等、事件五类、免注册。一个是当代临床的完整切片,一个是二十多年前的有限切片加一台外挂 Holter。

6.2 检索路径

站内检索用 slug ucddb,或全名里较短的 “UCD Sleep Apnea Database”。中文关键词建议用"呼吸事件清单"或"Holter 三导"再加睡眠,因为单搜"睡眠"会返回几十条分期基准。用"UCD"也能命中,但要注意它同时是加州大学戴维斯分校的缩写,需再补"都柏林"或"PhysioNet"区分。

按需求找:要分期基准与规模化验证,去 sleep-edf 系;要腕表分期与极低成本的部署,去 sleep-accel;要现代多通道临床综合记录,去 cps-dataset-sleep;要有创血压与心输出量,去 slpdb;要"双导脑电加三路呼吸通道加独立 Holter"这一组合,本库是站内几乎唯一的选择。

6.3 三张对照表:人群、标注、时间结构

三个维度分开列,因为它们恰好决定了一个睡眠库能做什么。

第一张是人群。

库 人群构成 受试者数 性别构成 是否含健康对照
本库 疑似呼吸障碍转诊者 25 21 男 4 女 无
slpdb OSA 评估者 16 全男 无
sleep-accel 一般成人 31 混合 未区分
sleep-edf 健康与障碍混合 数十 混合 部分含
cps-dataset-sleep 临床综合队列 一百余 混合 含

第二张是标注。

库 分期体系 分期粒度 事件类型数 事件是否含生理参数 判读人数
本库 R&K 30 秒 5 类加 2 个气道标记 含最低血氧与脉率变化 1
slpdb R&K 30 秒 十余种合并符号 不含 未说明
sleep-accel AASM 30 秒 0 无 设备推算
sleep-edf AASM 为主 30 秒 极少 无 未说明
cps-dataset-sleep AASM 30 秒 数十 部分含 多名判读员

第三张是时间结构,这一维最容易被忽略,却直接决定能不能做时序分析。

库 记录长度 是否整夜 是否多夜 是否含外挂设备
本库 5.9 至 7.7 小时 近整夜 单夜 有,三导 Holter
slpdb 2 至 7 小时 多为片段 单段 无
sleep-accel 多夜连续 是 是 本身就是外挂
sleep-edf 整夜 是 部分多夜 无
cps-dataset-sleep 整夜 是 单夜 无

把三张表叠起来看,本库的位置很清楚:人群中等、标注单一判读者但含生理参数、时间结构是单夜近整夜加一台外挂。它占的是"带并行心电与三路呼吸通道的老式临床记录"这个角。

§7 质量评估与局限性

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

先校正一个几乎一定会犯的误判:把"只有一个技师判读"读成"标注质量低"。

这两件事在这个库上方向不一定相同。单一判读者意味着没有评分者一致性可估,这是一个真实的局限;但它同时意味着全库 25 段的判读习惯是同一个人的,不会出现两位技师对同一格给出不同类别、且分界处呈锯齿状的情况。对下游任务而言,一致但可能有系统偏移的标注,与不一致但无系统偏移的标注,各有各的麻烦,不能简单说哪个更差。

第二个需要校正的误判是"2007 年发布的库就是 2007 年的技术"。采集在 2002 至 2003 年,判读用当时的 R&K 标准,这是合规的,不是落后。把它与 2010 年后按 AASM 标注的库放在一起比较,准确率的差距里有一部分是标准差异,不全是模型能力。

第三个误判是"文件写着 EDF,所以任何 EDF 工具都能原样读"。这批头部是设备导出的变体:日期填成占位值、每记录字节数与文件体积对不上、通道名不按定长字段对齐。多数库能勉强打开,但缩放因子与时间轴要自己核对,否则问题会在几周后以幅值不对或时间偏移的形式冒出来。

7.1 五维评分

按 DAIMS 的常用维度打分,每项一至五分,分数针对"作为呼吸事件检测与 R&K 分期参照"这个用途。

维度 分数 理由
数据规模 2 25 人、25 段、约 173 小时,训练容量不足,做参照够用
标注质量 3 同一技师判读、含血氧与脉率变化,但无一致性估计、事件粒度粗
任务适配 4 呼吸事件与分期配对齐全,三路呼吸通道与外挂 Holter 是加分项
文档完整 3 信号清单与贡献者分工清楚,时间戳、位宽与通道名三处待澄清
可获取性 5 免注册、ODC-BY、体积中等,四条下载路径都可用

合计十七分(满分二十五)。可获取性满分,任务适配接近满分,规模是硬伤,其余两项在中间档。与同期老库相比,它在"标注与信号配套"上更好;与后来的大型库相比,它在规模上差两个数量级。

「标注质量」这一项若按"标签是否存在歧义"打分,可以给四分,因为事件清单里连最低血氧和脉率变化都写了;若按"能否估计标注噪声"打分,三分偏高,因为没有任何一致性数据。它是少而详,不是多而稳。

7.2 标注质量的两层

第一层是符号是否清楚。分期八个整数、事件五类加两个气道标记,全部在官方页面上一屏读完。这种极简设计的好处是不存在"标注文件格式不统一"这类故障。

第二层是符号能承载多少信息。事件这一层它做得比同期库细:每次事件都带最低血氧、相对下降幅度、鼾声标记、觉醒标记,部分行还带心率与变化幅度。这些都是判读时顺手记下的生理参数,对呼吸事件的机制研究很有用。

薄的地方在于:事件只有时刻与总时长,没有逐秒起止;分期没有每段比例汇总;指数也无法逐次复算,要自己从清单里数。

还有一处要说明:官方未提到交叉判读。全库由 Patricia Boyle 一人完成,页面未说明是否有人抽检,做标注噪声估计时给不了第二条读数。

7.3 已知的、可枚举的偏差

偏差 表现 影响
单中心 一家医院连续半年 中心效应无法从内部估计
无健康对照 全部为疑似患者 没有正常睡眠结构的基线
性别失衡 21 男 4 女 无法做性别分层
年龄跨度大 28 至 68 岁 分层后每组样本个位数
排除心脏共病 已知无心脏病、无自主神经障碍 低估真实门诊人群的共病比例
单夜 每人只测一晚 无法估夜与夜之间的波动
记录略短 最长不到八小时 睡眠效率的分母偏小
单次判读 一人完成,无一致性数据 标注噪声不可估
时间戳失真 头内日期统一为 2001 年 无法按真实日期做季节或年际分析
帧数不齐 Holter 与主机帧数不同 跨设备对齐需自行估计

前五条是结构性的,改不了;后五条是历史条件与工程细节带来的,靠读取与说明可以缓解,但无法消除。

还有一处统计上的提醒:这个库的天然统计单位是人,不是格。一百七十多小时的记录按三十秒切是两万余格,但同一夜相邻格高度相关。按格算显著性,等于把一个人的一夜当成两万多个独立样本。

7.4 外部验证矩阵

这个库在文献里的用法,可以归成四类角色。判断依据是官方用途说明与信号构成,不涉及具体数值比较。

验证角色 做法 讲得通的地方 风险
呼吸事件检测 用事件清单做逐事件的检出与分类评估 五类事件有明确时刻与时长 25 人,难以分层
单导心电筛查 用 Holter 三导中的一路做暂停筛查 三导独立于多导仪,可做跨设备对照 时间偏移需先估
R&K 分期对照 训练模型后在本库上做外部检验 全夜、双导脑电与眼电齐全 类别需先映射 AASM
呼吸与心率耦合 事件前后对齐心率 事件行自带脉率变化 对齐误差会污染结论

第一类与第四类最贴合它的设计目的。第二类是近年的热门用法:用可穿戴或单导设备做居家筛查,需要一个"设备独立、标签可靠"的参照。本库的 Holter 恰好提供了这个条件,代价是那五千余帧的未对齐。

还有一类不常被提起却很合适的用法:教学。十四路通道、两份标注文件、一张八行的编码表,链路每一环都能在一节课里讲完,解压后只取一段时间样就够演示。

7.5 它为何能持续:靠一个把两套设备并排放在同一夜的安排

它自 2007 年发布以来只有一个版本、一次修订,之后没有持续维护,却仍被反复引用。原因不在规模,在于它保存了一种不太容易复制的观测:同一个人一整夜,十四路多导信号与一台独立 Holter 的三导心电同时存在,而且呼吸事件与睡眠期都由同一位技师逐条判出。

要做这件事,得有人愿意在睡眠监测的同一夜里再加一台 Holter,还得有人把两台设备的数据分别归档、分别标注。这在临床上是可行的,因为 Holter 本来就是门诊常备检查;但要让两家数据在同一夜里凑齐并公开,需要医院与工程团队各让一步。

成本也是原因。重做一次需要一间睡眠实验室、一套十四路多导系统、一台 Holter 记录仪、一名能判读整夜的资深技师,以及连续半年的转诊流量;下载只要一点三吉。

边界同样明确:一旦课题转向大规模训练、AASM 标准对齐或健康人群基线,它的短板立刻暴露。

§8 生态位与历史

8.1 历史沿革

这批数据诞生在 PhysioNet 从"心律失常库"扩展到"多参数多导记录"的中间阶段。它加入的方式很典型:医院提供原始记录,大学团队完成脱敏与归档,再交给平台托管。

从文件形态能读出年代。2002 年的多导仪已可直接导 EDF,所以主波形不是更早的 WFDB 三件套。但导出的文件带着厂商痕迹:通道名不按标准对齐、字节数与体积不符、日期填占位符,属于"当时能用、今天要打补丁"的类型。

2011 年的修订是典型补录:波形重传、受试者表更新,版本号未动,说明发布方把它当勘误而非新版本。

8.2 与挑战赛和聚合库的关系

它没有进过任何睡眠挑战赛。分区之后的睡眠类挑战赛大多围绕微觉醒检测与分期,赛题要的是规模与统一点位,与本库 25 人的体量和 R&K 标准都不相称。这意味着它没有官方划分、没有排行榜,也不会被刷分式研究快速消耗。

它与聚合型资源的关系恰好相反。聚合库用规模与统一标注换通用性,代价是把单次检查的细节磨平;本库规模小、标注老,但每一路通道、每一行事件都对应一次真实的判读动作。

它的出现时机也值得一提:那几年正是把心率变异当作呼吸事件替代指标的思路开始流行的时期,而连续六到八小时的三导 Holter 加三路呼吸通道,恰好适合验证这类思路。

8.3 生态位:呼吸事件一端的老参照

把站内外睡眠库按"呼吸事件标签的完整度"排:可穿戴库基本没有,分期基准有少量或没有,临床综合库有但需协议,本库与 slpdb 属于"有细标签且免注册"这一档。

它因此有三个稳定用途:呼吸事件检测的参照物、单导心电筛查的跨设备检验集、教学素材。

这个位置不容易被替代:拼一个更大的睡眠库不难,难的是在同一夜里再配一台独立的 Holter,并把呼吸事件逐条写进文本清单。

8.4 谁在用它,用来做什么

从信号构成与官方用途推断,引用集中在三个方向:呼吸事件的自动检测与分类、由心电或血氧推断呼吸暂停、睡眠分期方法在 R&K 体系下的验证。

还有一类不常被提及的用法:读取工具的回归测试。它只需要一个能解 EDF 的库就能读,却包含通道名拼写不一、位宽声明失真、两份标注格式不同这些边角情况,正好用来检验解析代码是否写得够稳。

三类用法都不要求大样本。课题一旦要求几百人以上,它就会被换掉。

§9 使用指引

9.1 三种角色的路径

呼吸事件检测方向的最短路径。 先用受试者表确认 25 个编号,再按 §5.3 把事件清单解析成结构化表。挑一段事件数较多的记录(事件文件体积可作为代理指标)先做一遍目视核对,确认时刻与波形对得上,再扩到全库。最后按人留一切分评估。

分期方向的最短路径。 先按 §2.2 的对照表把整数映射成期名,把 4 与 5 合并成深睡、剔除 6 与 7,再训练。评估时同时报 R&K 五类与合并后的四类两个口径,避免与他人的 AASM 结果混淆。

工程落地方向的最短路径。 先确认要的是离线分析还是在线筛查。离线可直接用;在线需要自己定义事件窗口与时间标签,本库帮不上忙,把它当"事件的离线上限"估计更合适。

角色 先做什么 别做什么 预期产出
呼吸事件检测 解析事件清单并目视核对 直接按空格分列读后六列 逐事件检出率与类型混淆表
睡眠分期 建编码映射并处理 6 与 7 假定数字即期号 两套口径的分期结果
工程落地 分清离线与在线 指望它给出逐秒标签 事件检测的上界估计
教学 取编号 002 的那一段演示 一上来就讲全库 完整链路的一次直观演示

9.2 一条最短的可用流程

这里只写一条最短路径,把"解析、对齐、统计"三步串起来。它不追求性能,只保证每一步都对得上。

#-- 最小可用流程:一段记录的分期序列与事件表并到一起
from pathlib import Path
import pandas as pd

rec = "ucddb002"
root = Path("ucddb")
#-- 一、分期:每行三十秒
st = [int(x) for x in (root / f"{rec}_stage.txt").read_text().split()]
stage = pd.DataFrame({"start": [i * 30 for i in range(len(st))],
                      "stage": st})
stage["end"] = stage["start"] + 30
#-- 二、事件:只取四列,前三行是表头
rows = []
for ln in (root / f"{rec}_respevt.txt").read_text().splitlines()[3:]:
    parts = ln.split()
    if len(parts) >= 4:
        rows.append({"time": parts[0], "type": parts[1], "sec": int(parts[3])})
ev = pd.DataFrame(rows)
print("分期格数", len(stage), "事件条数", len(ev))
print(ev["type"].value_counts().to_dict())

输出是两个数加一个类型计数。它们只用来确认解析正确,不做分布结论——25 人不足以支撑人群层面的比例推断。

换按人留一验证时,测试集须以人为单位,理由见 §5.6。

9.3 引用方式

官方要求同时引用数据集与平台。数据集那一条按 DOI 10.13026/C26C7D 与版本 1.0.0 引用,机构写作 University College Dublin 与 St. Vincent’s University Hospital 两方;平台那一条按现行建议引用其平台综述。

数据写到版本级:名称、版本、DOI、访问日期。若做过分期映射、通道重命名或 Holter 对齐,须在方法里写明,因为这些步骤会改变复现结果。

§10 AI 使用声明

项目 声明
文本生成 本文由 AI 辅助撰写,编辑负责结构与事实核对
数字来源 规模、结构、边界三类数字取自 PhysioNet 官方页面与该库公开文件
文件核验 RECORDS、SubjectDetails.xls、两份文本标注与多个 EDF 头经直接访问确认
口径冲突 头内每记录字节数与文件体积不自洽、Holter 与主机帧数不等,已在本篇并列呈现
论文信息 仅参考 Europe PMC 的检索结果,未定位到数据集专属论文全文
未核验内容 全部事件的逐条内容、各记录的分期比例、Holter 通道的导联归属
图像 无配图;封面为生成式提示词,不含真实波形
免责 本文不构成任何临床或工程建议;使用须遵守 ODC-BY 1.0 署名条款

常见误读(避坑清单)

说法 实际 证据
「UCD 是加州大学戴维斯分校」 UCD 指都柏林大学学院,爱尔兰 官方全名与联系人机构
「这是都柏林大学数据库」 采集方是圣文森特大学医院,大学只负责整理提交 官方致谢与联系信息
「有患者与健康人两组」 全部为疑似患者,无健康对照 官方摘要的受试者一段
「编号连续,共 27 段」 编号 002 至 028 缺 004 与 016,共 25 段 RECORDS 与受试者表
「分期里 1 是一期」 1 是快速眼动,一期是 2 官方编码表
「每人测了两夜」 一人一段,全部单夜 受试者表 25 行对 25 个编号
「每段只有 14 路」 主波形 14 路,另有独立 Holter 3 路 文件清单
「Holter 三导是 V5、CC5、V5R 可直接取用」 文件里通道名只有 chan 1 至 3,未标对应 打开 Holter 头文件
「事件有逐秒起止」 只有发生时刻与总时长 事件文件表头
「可以直接与 AASM 库比准确率」 分期与事件判据都是 R&K 时代,需先映射 官方分期说明

FAQ

Q1:ucddb 里的 UCD 指什么?
指 University College Dublin,即爱尔兰都柏林大学学院。全名是圣文森特大学医院与都柏林大学学院睡眠呼吸暂停库,采集在医院,整理与提交在该校电气电子与机械工程学院。

Q2:一共有多少人、多少段记录、多长时间?
25 名受试者各有一段记录,合计 25 段。受试者表逐行给出检查时长,加总约 173.2 小时。编号从 002 到 028 但不连续,缺 004 与 016。

Q3:每段记录多少路信号?为什么有的说 14 路有的说 17 路?
主波形文件 14 路,Holter 文件另含 3 路,合起来 17 路。但两套文件分别存放、未做逐采样点对齐,所以严格说是"14 路加独立 3 路",不是一条 17 路的记录。

Q4:分期整数 1 到底是快速眼动还是一期?
是快速眼动。官方对照表写 0 为清醒、1 为 REM、2 为一期、3 为二期、4 为三期、5 为四期。数字与期号整体错位,不能按"数字即期号"映射。

Q5:那个 6 和 7 是什么?
6 是伪迹,7 是不确定。R&K 原始体系只有六类,这两个是本库自己加的非常规类别。做多分类时必须先剔除或单列。

Q6:事件有哪些类型?
五类事件:阻塞型低通气、中枢型低通气、阻塞型暂停、中枢型暂停、混合型暂停。另有周期性呼吸与潮式呼吸两个气道模式标记,出现在第三列,不与事件类型混计。

Q7:Holter 的三路分别是哪三导?
官方摘要写 V5、CC5、V5R,但文件里的通道名只有 chan 1、chan 2、chan 3,没有一对一的对应。要知道哪路是哪导,只能靠波形形态判断。

Q8:为什么 Holter 的帧数比主机多?
官方明说录音日期与时间不可得。Holter 可能提前开始、延后结束,或两者兼有。差值无法从文件本身判定,需要用心率突变点做交叉对齐。

Q9:EDF 头里的字段为什么和文件体积对不上?
头里写着每个数据记录三千八百四十字节、每记录一秒、共两万二千四百七十个记录,三项相乘应得八十余兆,实际文件只有二十七点四兆。这是设备导出的 EDF 变体,字段未严格按规范填写;官方页面也没有给采样率,遇到这类文件要靠读取工具与体积交叉核对。

Q10:适合做深度学习分期吗?
可以作为外部验证集,不适合当主训练集。25 人单中心单夜,训练容量不够;但双导脑电与双导眼电齐全,适合检验跨中心与跨年代的稳健性。

Q11:许可允许商用吗?
ODC-BY 1.0 允许,包括商业用途,条件是署名。署名要覆盖数据集本身、PhysioNet 平台与相关论文三层。

Q12:它能和 sleep-edf 拼在一起用吗?
技术上可以,但要先解决三件事:分期体系映射、通道数对齐、采样率是否一致。拼起来适合做跨年代稳健性检验,不适合把两边的格直接混成一个训练集。

术语表

术语 解释
多导睡眠图 同时记录脑电、眼电、肌电、呼吸与心电等多项生理信号的整夜检查
阻塞型睡眠呼吸暂停 睡眠时上气道反复塌陷导致气流停止或显著减少的疾病
中枢型呼吸暂停 呼吸中枢发出的驱动不足导致的气流停止,与气道是否堵塞无关
混合型呼吸暂停 以中枢型起始、以阻塞型收尾的一次暂停
低通气 气流幅度显著下降但未完全停止的一段呼吸
呼吸暂停低通气指数 每小时睡眠中呼吸暂停与低通气的次数,严重程度的核心指标
R&K 分期 Rechtschaffen 与 Kales 提出的五期分期体系,本库所用标准
AASM 分期 美国睡眠医学会的现行体系,深睡合并为 N3
快速眼动期 眼球快速运动、肌张力极低的一段睡眠,本库编码为 1
慢波睡眠 以高幅低频脑电为主的深睡阶段,本库分成三期与四期
睡眠效率 实际睡眠时长占卧床时长的比例
日间嗜睡量表 评估白天打瞌睡倾向的问卷,本库表中有一列
Holter 可随身佩戴的长时间心电记录仪,本库用 Lifecard CF
导联 心电图电极的连接组合,如 V5、CC5、V5R
热敏气流信号 靠口鼻处温度变化记录呼吸的设备,对低通气灵敏度有限
呼吸带 绑在胸腹的应变带,记录呼吸运动,本库未做标定
血氧饱和度 血液中与氧结合的血红蛋白占比
周期性呼吸 呼吸幅度呈周期性增减的模式
潮式呼吸 周期性呼吸的一种,幅度由小到大再由大到小
EDF 欧洲数据格式,多导生理信号的通用存储标准
数据记录 EDF 文件的基本单元,一个记录含各通道若干采样点
定宽文本 按固定列位对齐的纯文本表格,本库事件文件即此格式
去标识 移除姓名、病历号等直接标识符的处理
评分者一致性 多名判读员对同一份记录判读结果的吻合程度
受试者泄漏 同一受试者的样本同时出现在训练与测试集,导致成绩虚高
ODC-BY 开放数据共享署名许可,允许商用需署名

附录 A:核心数字核对表

项 值 来源 来源层级
受试者数 25 官方摘要 官方页面
记录数 25 RECORDS 五十行除以二 官方文件
性别构成 21 男 4 女 官方摘要与受试者表 官方页面
年龄均值 50 岁 官方摘要 官方页面
年龄范围 28 至 68 岁 官方摘要 官方页面
体质指数均值 31.6 官方摘要 官方页面
体质指数范围 25.1 至 42.5 官方摘要 官方页面
呼吸暂停指数均值 24.1 官方摘要 官方页面
呼吸暂停指数范围 1.7 至 90.9 官方摘要 官方页面
检查时长范围 5.9 至 7.7 小时 受试者表 官方文件
合计时长 约 173.2 小时 受试者表逐行相加 官方文件推算
主波形通道 14 EDF 头 官方文件
Holter 通道 3 EDF 头 官方文件
记录节拍 每数据记录一秒 头部字段 官方文件
逐路采样率 官方未给 官方页面 未核实
位宽 16 位 EDF 格式规范 官方页面(格式声明)
分期编码 0 至 7 官方页面 官方页面
事件类型 5 类 事件文件与官方页面 官方文件
未压缩体积 1.3 GB 页面文件区 官方页面
许可 ODC-BY 1.0 页面许可栏 官方页面
数据 DOI 10.13026/C26C7D 页面发现栏 官方页面
首发日期 2007-10-09 页面版本说明 官方页面
修订日期 2011-09-01 官方摘要 官方页面

附录 B:数字的来源分层

第一层,官方页面与官方文件。 受试者数、性别、年龄、体质指数、呼吸暂停指数的均值与范围、通道数、分期编码、事件类型、体积、许可与 DOI,全部来自项目主页;时长与数据记录数来自受试者表;通道名与帧数来自各 EDF 头,位宽按 EDF 规范为 16 位。合计时长由受试者表逐行相加得出。这一层可直接引用,重查可得同样结果。

第二层,论文摘要与题录。 本文未能通过 Europe PMC 定位到以本数据集为对象的专属论文,检索返回的是引用该库的下游研究。因此论文层只支撑"这个库被谁用过",不支撑"作者主张了什么"。正文涉及用法的地方,均按信号构成推断,未引具体结论。

第三层,未核实。 全部事件的逐条内容、各记录的分期比例、Holter 三路通道各自对应哪一导、Holter 与主机之间那五千余帧的实际归属、体位编码的含义、日间嗜睡量表与睡眠效率两列在官方正文中的地位。正文凡涉及这些的地方,都只做定性表述或明确标注为推断。

附录 C:完整参考文献

编号 文献 链接 用途
1 St. Vincent’s University Hospital / University College Dublin Sleep Apnea Database v1.0.0 https://physionet.org/content/ucddb/1.0.0/ 规模、结构、边界数据
2 该库文件目录 https://physionet.org/files/ucddb/1.0.0/ EDF 头、RECORDS、两份标注、受试者表
3 受试者人口学与检查摘要表 https://physionet.org/files/ucddb/1.0.0/SubjectDetails.xls 时长、性别、编号
4 记录清单 https://physionet.org/files/ucddb/1.0.0/RECORDS 遍历入口与记录数
5 PhysioNet 平台综述(2026,Nature Health) https://doi.org/10.1038/s44360-026-00096-z 托管模式与引用规范
6 ODC-BY 1.0 许可全文 https://opendatacommons.org/licenses/by/1-0/ 许可条款
7 EDF 格式规范 https://www.edfplus.info/specs/edf.html 头字段与数据记录的定义
8 Rechtschaffen 与 Kales 判读手册的通行转述 https://doi.org/10.1093/sleep/33.12.1553 分期体系的历史背景

附录 D:任务代码

把一段记录的分期色带与事件时刻画在同一张时间轴上,下面这段够用,不需要训练模型。

#-- 分期色带与事件竖线叠在一张图里
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np

rec, root = "ucddb009", Path("ucddb")
st = np.array([int(x) for x in (root / f"{rec}_stage.txt").read_text().split()])
hours = np.arange(len(st)) * 30 / 3600

fig, ax = plt.subplots(figsize=(12, 2.4))
ax.imshow(st[None, :], aspect="auto", cmap="viridis",
          extent=[0, hours[-1], 0, 1])
for ln in (root / f"{rec}_respevt.txt").read_text().splitlines()[3:]:
    p = ln.split()
    if len(p) < 2:
        continue
    h, m, s = (int(x) for x in p[0].split(":"))
    ax.axvline(h + m / 60 + s / 3600, color="w", lw=0.4, alpha=0.6)
ax.set_yticks([])
ax.set_xlabel("hours since record start")
plt.tight_layout()
plt.savefig("ucddb009_timeline.png", dpi=120)
print("格数", len(st), "时长小时", round(hours[-1], 2))

输出是一张色带图,横轴为小时,每条白色竖线是一次呼吸事件。若竖线密集处与色带颜色同时在变,说明事件与分期在时间上确实同步;若整体错位,多半是事件时刻用了真实钟点而色带从零点起算,需要先减起始时刻。

附录 E:如果只记五件事

第一,UCD 指爱尔兰都柏林大学学院,采集在都柏林圣文森特大学医院,不是美国那几所学校。

第二,25 名成人、25 段整夜记录、合计约 173 小时,男女混合但男性占绝大多数,没有健康对照。

第三,主波形 14 路 EDF,外加一台独立的 Holter 三导心电,两套文件未逐点对齐。

第四,分期用 R&K,整数 0 为清醒、1 为快速眼动、2 至 5 对应一到四期,另有 6 伪迹与 7 不确定。

第五,事件是独立文本清单,五类事件带最低血氧与脉率变化;现实的用法是呼吸事件检测与跨设备检验。

编辑说明

核验时间 2026 年 10 月 28 日。核验方式:直接访问 PhysioNet 项目页与文件目录,读取 RECORDS、SubjectDetails.xls 与部分 _stage.txt、_respevt.txt,并解析多个 .rec 与 _lifecard.edf 的头部字段,核对通道名、帧数、位宽与起始日期。论文信息经 Europe PMC 检索,未找到以本库为对象的专属论文。未覆盖:全部事件的逐条内容、各记录的分期比例、Holter 通道的导联归属、体位编码含义。受试者数 25 与编号缺号按并列呈现;采样位数与位宽按两个口径并列,未作判断。


相关数据集导航

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

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

返回 AI-Ready 数据集