信息速览
监护仪在床边每两秒吐出一批数字,一天下来是几万条;护士在病历里记下的,是每隔几小时一次的体温、几个风险评分。这两套记录写的是同一个人、同一段时间,却在绝大多数医院里永远对不上时间——遥测系统按设备时钟存,病历按录入时刻存,中间隔着一道谁也说不清的偏移。更麻烦的是隐私这一层:为了合规,绝大多数公开的病历数据集在发布前把时间戳整体抹掉,或者随机化到无法对齐的程度,于是「某一次报警拉响之后多久叫来了应急响应团队」这类问题,在公开数据里根本没有答案。ALOTT(ALarms, Outcomes Telemetry with Timing,带时间的报警与结局遥测)正是冲着这道缺口来的:俄亥俄州立大学与 GE 从 2018 年起把两家医院全部病床的监护仪输出流下来,再和电子病历按患者与住院逐条对齐,并且刻意保留了事件相对于本次就诊起点的相对时间——只把绝对日期按人整体平移,而不把它打散。
它的稀缺性在于「两头都不缺」。公开世界里,波形库很多,病历库也很多,但能把 240 Hz 心电波形、两秒级测量值、报警流水与同一次住院的检验、用药、护理流程表放在同一条时间轴上的库极少;它的代价同样明确:受限于数据使用协议、单中心、两家专科医院、没有年龄字段、患者级人数未公布、且官方自己称为试点项目(pilot project)。它不是规模上的大库,是一件专门用来研究「时间关系」的工具。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | ALarms, Outcomes Telemetry with Timing (ALOTT): a Bedside-EMR Database |
| 发布方 | PhysioNet(由 MIT 计算生理实验室维护) |
| 贡献机构 | 俄亥俄州立大学 Wexner 医学中心,与通用电气(GE)合作采集 |
| 署名作者 | John Lawrence、Mike Rayo、Timothy Huerta |
| 首次发布 | 2025 年 3 月 19 日,版本 1.0.0 |
| 最近改动 | 版本历史只有 1.0.0 一条,官方称其为首个公开发布版本 |
| 病床数 | 270 张 |
| 住院次数 | 超过 15,000 次住院 |
| 患者数 | 官方未公布(以 aMRN 掩码标识,未给出去重人数) |
| 时间跨度 | 2018 年 9 月至 2020 年 11 月 |
| 波形与采样率 | 心电、血氧等遥测波形,60–240 Hz |
| 测量粒度 | 体温、脉搏、灌注等非波形测量,两秒一个间隔 |
| 病历表数量 | 10 张 CSV(过敏、人口学、社会史、住院、位置、ICU、医嘱、检验、用药、流程表) |
| 文件格式 | WFDB(.hea / .dat)+ CSV 平表 |
| 标注方式 | 非人工标注;由监护仪与病历系统原始输出经程序转换,事件为系统原生的报警与流程表记录 |
| 许可与访问 | PhysioNet 受限健康数据许可 1.5.0,须注册、通过审核并签署数据使用协议 1.5.0 |
| 标识符 | DOI 10.13026/sbq5-dy17(v1.0.0);最新 DOI 10.13026/46e5-hh23 |
| 典型用途 | 应急响应团队事件预测、病情恶化早期预警、报警负担与报警疲劳研究、时序异常检测 |
§1 它要解决的具体麻烦
1.1 预警这件事,卡在"时间"而不是"数据"
临床上判断一个患者正在恶化,靠的从来不是某一个数值越界,而是一组微弱、非特异的信号在时间上的组合:心率慢慢爬上去,血压的波动幅度变小,氧饱和度在夜里反复掉到某个水平,护士记的风险评分一次比一次高。这些信号单拿出来都不构成诊断,合在一起才有意义——而"合在一起"这四个字,前提是它们共享同一条时间轴。
现实是它们不共享。床旁监护仪是一个独立的设备网络,它按自己的时钟连续输出,颗粒度是两秒甚至 240 Hz;电子病历是一个人工录入系统,它按护理班次、按医嘱执行时刻记录,颗粒度是分钟到小时,而且录入时刻往往滞后于事件本身。医院内部把这两套系统打通的成本极高,绝大多数机构只做到了"能看",没做到"能算"。
公开发布则把这个问题推到了极端。以 MIMIC-III 为代表的遥测—病历配对库,为了保护患者隐私,普遍采用日期整体随机平移的做法,有的甚至把相对时间也一并打散。官方页面在背景部分直接点明了这一点:多数这类数据集不保留患者事件的时间。于是"报警先于应急响应多久""波形上的一次短暂低氧是否被护士记录到"这类问题,在公开数据上无法回答。
ALOTT 的做法是一次刻意的设计取舍:保留相对时间,模糊绝对日期。每一次住院内部的事件顺序、间隔、昼夜节律都完整保留,而每个患者被赋予一个 −180 到 180 天之间的随机偏移,整体平移;一天之内的时刻不平移。这个取舍让"时序模式"这类研究成为可能,同时不暴露任何真实的日历日期。
1.2 三条常见的错误期待
第一条,期待它是"另一个 MIMIC"。它在数据来源形态上像 MIMIC——波形加病历,但人群完全不同:两家专科医院,一家是综合癌症中心,一家是心脏医院,而不是综合 ICU 的混合人群。拿它训练出的模型不能默认外推到普通内科病房。
第二条,期待它有"人工标注的恶化标签"。它没有。应急响应团队事件来自护理流程表,是临床流程中留下的记录,不是研究者事后逐段判读的金标准。标签的定义、完整性与一致性,取决于流程表怎么填。
第三条,期待它"下载即用"。它是受限访问数据,文件目录在未授权状态下返回 403,官方也明确写出部分地区因法律或政策原因不可获取。从申请到拿到数据要走过账号、凭据审核与数据使用协议三步,这跟开放获取的波形库完全是两种体验。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 报警与临床事件的时间先后关系 | 报警流水带时间戳,流程表带时间戳,相对时间完整 | 够,这是它最不可替代的一点 |
| 高分辨率波形上的形态分析 | 60–240 Hz 心电与血氧波形,WFDB 格式 | 够,但通道清单官方未逐项列出 |
| 两秒级的生命体征趋势 | 体温、脉搏、灌注等两秒间隔测量 | 够做趋势与斜率类研究 |
| 检验、用药、医嘱的顺序分析 | 十张病历表覆盖医嘱、检验、用药 | 够,且可与遥测对齐 |
| 病情恶化的金标准标签 | 流程表中的应急响应团队事件 | 不够,无人工复核,定义依赖录入 |
| 患者年龄分层 | 官方明确说明诚实经纪人未提供年龄,该字段为空 | 不够,任何年龄分层研究都做不了 |
| 多中心泛化验证 | 单一机构、两家专科医院 | 不够,只能做"跨人群"而非"跨中心" |
| 患者级人数统计 | 只给病床数与住院次数 | 不够,去重患者数官方未公布 |
| 报警疲劳与报警负担研究 | 平均每次住院 28,193 条报警,含静音与停用状态 | 够,且是少见的大规模真实报警流水 |
| 呼吸机使用相关分析 | 流程表含呼吸机使用记录 | 可做,粒度取决于录入密度 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你在做恶化预警模型,但手上的数据没有相对时间 | 提供保留相对时间的遥测—病历配对数据 | 先确认你的标签口径如何与流程表中的应急响应事件对应,再决定预测窗口 |
| 你在研究报警疲劳,缺真实报警流水 | 报警名称、触发值、上下限、静音与停用标志齐全 | 按报警名称聚合前先统一命名,官方未保证命名规范一致 |
| 你想验证"波形上的事件是否被病历记录到" | 两套数据以 aMRN 与 aCSN 关联,时间可对齐 | 先做日期偏移还原,再用位置表锁定患者在哪个床位 |
| 你在做时序异常检测,缺长序列真实数据 | 两秒级测量与高采样波形构成长序列 | 注意波形按日切分成多个文件,跨文件拼接要在时间轴上做 |
| 你想复现某个基于 MIMIC 的预警模型 | 提供不同的机构与人群,作为外部测试面 | 人群差异大,掉分不能直接读作模型更差 |
| 你在做医疗数据工程,想学一套脱敏流水线 | 官方公开了完整的转换代码仓库 | 重点看日期偏移与映射表删除这两步 |
1.5 一句话判断
它不是"更大的病历库",而是"唯一敢把时间留下来的那一个":如果你的研究问题里含有"先—后"或"多久",它的价值立刻显现;如果不含,它的获取成本就很难收回。
1.6 不适合谁:四条边界
不适合需要年龄分层的任何研究。 官方明确写明诚实经纪人未提供年龄,该字段在数据集中不是已填充变量。儿童、老年、年龄分层评估一律做不了。
不适合需要开放获取的场景。 受限访问意味着不能放进公开的代码仓库、不能在未签署协议的机器上落地、也不能作为竞赛题直接发布。教学演示、公开课示例、黑客松都不合适。
不适合需要跨机构验证的论文。 两家医院同属一个医学中心,共享同一套病历系统、同一批监护设备、同一套录入规范。它能检验"换一家医院行不行",但不能检验"换三家医院行不行"。
不适合把报警当作可靠临床事实来用。 监护仪报警以假阳性著称,官方给出平均每次住院 28,193 条报警这个量级本身就说明了问题。它适合研究"报警本身",不适合把报警当作疾病的代理指标。
§2 数据构成与规格
2.1 两个来源、两类文件
ALOTT 的数据来自两条完全独立的管道。第一条是床旁监护仪:两家医院所有床位的监护仪输出通过 GE 的 Bernoulli 系统流式写入一个安全网络盘,产出报警、测量、波形三类文件。第二条是电子病历:通过诚实经纪人(honest broker)申请,从病历信息仓库导出 SQL 表,去标识、日期平移后落成 CSV 平表。
官方对数据集构成的描述是"十张病历信息仓库文件,加上一批按患者与住院分组的 WFDB 与 CSV 遥测文件"。两条管道的交汇点是两个掩码标识符:aMRN(掩码后的患者标识符,由病历号映射为不重复的随机整数)与 aCSN(掩码后的就诊标识符,由接触序列号映射而来)。所有文件都能通过这两个键互相连接。
Bernoulli 系统的原始输出是层次化的 XML,每个文件最多含 30 分钟数据,内部按两秒一个元素切分;每个两秒元素里装着患者标识、报警、测量与波形。转换流水线把这些 XML 摊平成文件,按患者、住院、时间拆成报警、测量、波形三支;波形再按连续读取段切开并转成 WFDB 文件,报警与测量合并成 CSV。全部转换代码公开在官方给出的代码仓库里。
2.2 十张病历表的字段字典
这十张表是数据集里"人"的那一半。它们的共同点是:全部去标识、全部日期平移、全部以 aMRN 或 aCSN 为主键的一部分。
| 表名 | 每行代表什么 | 主要内容 | 使用注意 |
|---|---|---|---|
| allergies | 一个患者对一种过敏原的一条记录 | 过敏原与反应 | 以 aMRN 关联,与住院无关 |
| demographics | 一名患者 | 种族、民族、婚姻状况、性别、语言、血型 | 官方未提供年龄,此处也没有年龄 |
| social_Hx | 一名患者 | 自报的烟草、酒精与非医用药物使用 | 自报字段,完整性取决于问诊 |
| admissions | 一次住院 | 入出院时间与地点、主要与次要诊断、住院时长 | 主要分析单位,以 aCSN 为键 |
| location | 一次在床 | 患者在哪个床位、何时在、住了多久 | 与遥测对齐的关键桥梁 |
| ICU | 一次 ICU 在床 | 是否在 ICU 或普通病房床位 | 官方页面将 location 与 ICU 并列描述 |
| orders | 一条医嘱 | 开了什么、何时执行、结果如何 | 与 lab、medication 同构 |
| lab | 一次检验 | 检验项目、执行时间、结果 | 官方给出平均每次住院 266 条实验室测量 |
| medication | 一次给药 | 药物、给药时间、结果 | 与 orders 字段结构相近 |
| flowsheet | 一条护理记录 | 生命体征、风险评分、应急响应事件 | 标签来源,也是官方点名的核心表 |
这十张表里,对预警研究最重要的是 flowsheet。官方对它的定义是"由提供者录入的、带时间戳的患者数据,每一行包含生命体征、风险评分与应急响应事件"。换句话说,应急响应团队事件不是单独一张表,而是混在护理流程表里,靠记录类型区分。
2.3 遥测三类文件与它们的字段
遥测部分按患者目录再按住院目录组织,每个住院目录里放该次住院的报警、测量与波形文件。
| 文件类型 | 命名规则 | 每次住院的数量 | 格式 |
|---|---|---|---|
| 报警 | ALARMp<aMRN>e<aCSN>.csv |
一个 | CSV |
| 测量 | MEASUREMENTp<aMRN>e<aCSN>.csv |
一个 | CSV |
| 波形头文件 | p<aMRN>e<aCSN>d<yyyymmdd>T<hhmmss>.hea |
每天每段连续读取一个 | WFDB 文本头 |
| 波形数据 | p<aMRN>e<aCSN>d<yyyymmdd>T<hhmmss><A-Z>.dat |
一个头对应一个或多个数据文件 | WFDB 二进制 |
文件名里的 d 与 T 段是波形的起始日期与时间。因为日期已被整体平移,这个日期不是真实日历日期,但段内与段间的相对关系有效。
报警表的字段如下:
| 字段 | 含义 | 使用注意 |
|---|---|---|
| alarmName | 被触发的报警名称 | 官方举例为血氧溶解量与心率高低;命名规范未保证统一 |
| pollTime | 该报警处于活动状态的时刻 | 两秒粒度下的轮询时刻 |
| setLow / setHigh | 不触发报警的正常范围上下限 | 上下限由临床设置,因人而异 |
| chanValue | 触发报警的那个值 | 与 setLow / setHigh 一起可判断是否越界 |
| sil | 等于 1 表示该报警被静音 | 研究报警疲劳的关键字段 |
| inactivationState | 报警是否被停用 | 停用意味着这段时间该报警根本不会响 |
| abnormalFlags | 报警级别与类型的文本表示 | 文本字段,口径可能需要归并 |
测量表的字段如下:
| 字段 | 含义 | 使用注意 |
|---|---|---|
| pollTime | 采集该测量的时刻 | 与报警表同名同义,可对齐 |
| mesname | 测量名称 | 官方举例为体温、脉率、呼吸率 |
| msite | 测量取自哪个部位 | 同一名称可能有多个部位 |
| muom | 该测量的单位 | 单位换算前必须读 |
| mtext | 测量值 | 文本存储,需转数值 |
波形部分是 WFDB 标准文件。官方说明波形文件按患者切成连续读取段,包含该患者在本次住院中按日采集到的全部波形。通道清单与每条通道的采样率需要从 .hea 读,官方页面只给出 60–240 Hz 这个整体区间,并举例提到 240 Hz 的心电波形。
2.4 主键映射与日期偏移:三个必须理解的设计
第一层是标识符掩码。 病历号被映射为不重复的随机整数 aMRN,接触序列号被映射为不重复的随机整数 aCSN。这一步之后,原始标识符不再出现在任何文件里。
第二层是日期平移。 每个 aMRN 被赋予一个 −180 到 180 天之间的随机偏移,该患者的所有日期统一平移。关键细节:一天之内的时刻不平移。这意味着昼夜节律、班次差异、夜间恶化这类研究是可行的,而跨患者的日历对齐(比如把两名患者的"第二天"放在一起比)是不可行的。
第三层是遥测与病历的匹配算法。 官方描述得很具体:先用病历号加日期把遥测文件匹配到住院;匹配不上时,改用位置加日期判断那个时间点哪个患者应该在那张床上。一旦某个遥测文件确定了病历号,它的日期就按该病历号对应的随机偏移平移。全部映射完成、日期全部平移之后,映射表被删除——官方用词是"把编码的有限数据集转换为有限数据集"。这一步的后果是:匹配错误无法在事后追溯,也没有留给你纠错的对照表。
2.5 一次住院的完整解剖
把上面几节拼起来,一次住院在数据集中长这样:
p12345/ #-- 患者目录,aMRN = 12345
├── ALARMp12345e67890.csv #-- 本次住院全部报警
├── MEASUREMENTp12345e67890.csv #-- 本次住院全部两秒级测量
├── p12345e67890d20190512T143000.hea #-- 一段连续波形的头文件
├── p12345e67890d20190512T143000A.dat #-- 该段波形的数据文件
└── p12345e67890d20190513T021500.hea #-- 另一段(不同起始时刻)
一次住院的分析单位因此是"一整棵目录",而不是单个文件。报警与测量各只有一个文件,覆盖整次住院;波形则按天、按连续读取段切成若干对 .hea / .dat。想要一段完整的连续波形序列,必须按文件名里的时间戳排序后拼接,中途的缺口代表监护中断、转床或设备更换。
官方给出的"平均每次住院"的量级如下,这几个数字是评估工作量与存储需求时最实用的参考:
| 项目 | 官方给出的平均量级 | 含义 |
|---|---|---|
| 护理记录 | 779 条 | 流程表等人工录入的观察 |
| 实验室测量 | 266 条 | 检验结果 |
| 遥测报警 | 28,193 条 | 报警流水,两秒粒度下累计 |
| 240 Hz 两秒波形段 | 524,744 段 | 波形文件的切分单元 |
| 两秒粒度遥测测量 | 1,020,071 条 | 非波形测量值 |
这五个数字需要一句提醒:官方把它们写作"每次住院平均",但同一页给出的中位住院时长是 69 小时、中位 ICU 停留时长是 128 小时。把两组数字放在一起看,量级上并不自洽,官方也没有解释这些均值是按每次住院、每床日还是按别的口径统计的。把它们当成"量级指示"来估计存储与算力是安全的,当成精确的每次住院期望值来写进论文的样本量计算则不安全。这一点已列入 §10 的未核验项。
2.6 与同类资源的字段差异
| 对比项 | ALOTT | 典型重症电子病历库 | 典型公开波形库 | 典型报警标准库 |
|---|---|---|---|---|
| 波形采样率 | 60–240 Hz | 通常无波形 | 125–500 Hz | 固定测试波形 |
| 非波形测量粒度 | 两秒 | 分钟到小时 | 通常无 | 无 |
| 报警流水 | 有,含静音与停用状态 | 通常无 | 通常无 | 有,但是合成的 |
| 病历表 | 10 张 | 数十张 | 无 | 无 |
| 相对时间 | 保留 | 多数被抹除 | 天然保留 | 不适用 |
| 绝对日期 | 按患者整体平移 | 多数被抹除或整体平移 | 通常无日历意义 | 无 |
| 年龄字段 | 无 | 有 | 通常有 | 不适用 |
| 访问方式 | 受限,须签协议 | 受限,须签协议 | 多为开放 | 多为开放 |
这张表要说清的只有一件事:ALOTT 的价值集中在"报警 + 波形 + 病历 + 相对时间"这四项的交集上。任何单独一项都有更好的替代品,四项同时成立且互相可对齐的,公开范围内很少。
§3 它是谁的数据:一家癌症中心与一家心脏医院的监护仪流水
3.1 贡献者与机构
数据集由俄亥俄州立大学(The Ohio State University,OSU)团队发布在 PhysioNet 上,署名作者三人:John Lawrence(医学院与生物医学科学研究生项目)、Mike Rayo(转化数据分析研究所核心教师、综合系统工程助理教授)、Timothy Huerta(Wexner 医学中心与医学院研究信息技术与首席研究信息官副院长、家庭与社区医学教授、生物医学信息学教授)。三人的共同背景是人因工程与临床信息学,这正是本数据集的设计基调:它不是一个由临床科室顺手捐出的数据库,而是一个为"预警算法研究"专门设计的数据工程产物。
采集侧的合作方是通用电气(GE)。2018 年,OSU 与 GE 开始把两家医院全部病床的监护仪输出落盘,用的是 GE 的 Bernoulli 系统。理解这一点很重要:数据的形态由这套系统决定——XML、最多 30 分钟一卷、两秒一个元素、报警与测量与波形三支分流。后文所有的"为什么文件是这样切的",答案都在这套系统的输出规范里,而不在研究者的设计偏好里。
两家医院分别是 The James 综合癌症中心与 Solove 研究所(简称 The James)和 Richard M. Ross 纪念心脏医院(简称 The Ross)。官方页面在摘要里写作 James Cancer Hospital 与 Ross Heart Hospital。人群因此高度专科化:一边是肿瘤住院患者,一边是心脏住院患者。
3.2 时间线
| 时间 | 事件 | 意义 |
|---|---|---|
| 2013 / 2019 | 机构审查委员会批准项目(编号 2013H0419、2019H0058) | 伦理前置,知情同意被豁免 |
| 2018 年 | OSU 与 GE 启动全病床遥测采集 | 数据开始积累 |
| 2018 年 9 月 | 数据集收录窗口起点 | 见摘要 |
| 2020 年 11 月 | 数据集收录窗口终点 | 见摘要 |
| 2023 年 | 转换代码以预发布形式存档(Zenodo DOI 10.5281/zenodo.7922122) | 流水线先于数据公开 |
| 2025 年 3 月 19 日 | 版本 1.0.0 在 PhysioNet 上线 | 首个公开发布版本 |
版本历史只有 1.0.0 一条,官方的发布说明也只写了一句话:1.0.0 是本数据库的首次公开发布。也就是说,截至核验时间,它还没有修订版,没有补遗,没有勘误记录。这对使用者有两层含义:好的一面是不存在"你用的是哪个版本"的混淆;坏的一面是任何发现问题都只能自己去核对,没有官方修订可对照。
3.3 采集场景:常规诊疗的副产品,不是研究队列
官方在方法部分写得明白:ALOTT 装的是常规住院诊疗过程中产生的数据,采集本身不给患者带来任何额外负担。这句话决定了它的性质——它不是前瞻性研究队列,没有入组标准、没有随访计划、没有预设的终点事件,而是"把本来就在发生的事情录下来"。
这带来几个直接后果。第一,数据的完整性取决于临床流程:患者转到不做遥测的病房,波形就断了;护士忙,流程表就记得稀;监护仪被关掉做检查,报警也就没有了。第二,人群是"所有上了遥测床位的患者",而不是某个诊断的队列,所以诊断构成由两家医院的收治结构决定。第三,没有干预,也就没有干预效果可评估。
官方给出的人群画像只有三行:57.8% 的患者为男性;ICU 中位停留时长 128 小时;住院中位时长 69 小时。这三行是官方页面唯一给出的人群层面定量描述,其余(种族构成、年龄、主要诊断分布)都没有出现在页面上。
3.4 数据来源的两个层次与一次不可逆的删除
理解这份数据,要先分清两层:床旁监护仪流水(原始,连续、自动、高频)与电子病历仓库导出(人工、稀疏、结构化)。前者回答"设备上发生了什么",后者回答"人记录了什么、做了什么、结局如何"。两层之间的对应关系不是天然存在的,而是靠算法建起来的。
建完即删是这个数据集最值得注意的工程决策。官方写得很具体:遥测与病历先用病历号加日期匹配,匹配不上再用位置加日期判断那个时刻谁在那张床上;一旦确定,就把该患者的日期按随机偏移平移;全部映射完成、日期全部平移之后,映射表被删除,目的是把编码的有限数据集降级为有限数据集。
对使用者来说,这一步的后果是三重的。其一,你无法知道某次住院的遥测是靠病历号匹配的还是靠床位位置推断的,两者的可信度并不相同。其二,如果匹配有错,事后无从发现,也没有纠错表可查。其三,这也是它的隐私设计的一部分——即使拿到全部文件,也无法把两个不同患者的记录串起来。这是优点也是代价,取决于你站在哪一边。
§4 它最独特的东西:敢于留下"先后"
4.1 相对时间这件事,为什么别人做不到
公开病历数据集抹掉时间,不是技术偷懒,而是合规上的必然。 timestamps 加上诊断、用药、地点,重识别的风险会陡然上升;把日期整体平移可以降低风险,但一旦保留相对时间,事件之间的间隔、昼夜模式、护理班次节奏就都还在,这些本身也是准标识符。
ALOTT 的选择是保留相对时间、平移绝对日期,并把平移量限制在 −180 到 180 天之间。这个区间不是随意的:它足够大,能把患者散开到无法按日历对齐;又足够小,不至于把季节性疾病的时间关系彻底打乱。同时,一天之内的时刻不平移——这是整个设计里最聪明的一笔,它让"夜间恶化"“凌晨报警”"交接班前后"这类研究全部保留可行,而这些恰恰是病情恶化研究里最有临床味道的部分。
官方在背景里把这一点写成了数据集的目标之一:提供一份便于构建时序模式的数据集。换句话说,它存在的理由不是"数据多",而是"时间还在"。
4.2 报警流水:一个被低估的资源
监护仪报警在临床研究里长期处于尴尬位置——人人都说它太多、太吵、太不可信,但几乎没人有真实的报警流水可以量化这句话。ALOTT 把这个缺口补上了:报警名称、触发时刻、上下限、触发值、是否被静音、是否被停用、以及文本化的级别与类型,全部按两秒粒度留在表里。
这打开了几类此前很难做的研究:
| 研究问题 | 需要的字段 | 它能提供什么 |
|---|---|---|
| 报警负担到底多大 | 报警名称与 pollTime | 官方给出平均每次住院 28,193 条报警 |
| 哪些报警最常被静音 | alarmName 与 sil | 可按名称统计静音情况 |
| 停用与静音是否影响结局 | inactivationState、sil 与流程表中的应急响应事件 | 两组数据时间可对齐 |
| 报警阈值设置是否合理 | setLow、setHigh 与 chanValue | 可回看越界幅度 |
| 报警与波形是否互相印证 | 报警时间戳与波形起始时间戳 | 可回到波形上核对那两秒 |
| 报警文本是否规范 | abnormalFlags | 文本字段,可做命名一致性研究 |
这张表里最有价值的一行是最后第二行:把报警时刻映射回波形,是绝大多数公开数据做不到的事。它让"这条报警是真的吗"从一句争论变成一个可以查的实验。
4.3 案例:从一条报警回到两秒波形
设想一次典型的核对。从某次住院的报警表里取出一条心率过高报警,记下它的 pollTime;在测量表里找同一时刻附近的脉率测量,看 mesname 与 mtext 是否印证;再到波形目录里按文件名时间戳定位覆盖该时刻的 .hea / .dat 对,读出那几秒的心电波形,人工判断报警是否为假阳性。
import pandas as pd
import wfdb
#-- 三个文件来自同一次住院(aMRN=12345, aCSN=67890)
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'])
meas = pd.read_csv('MEASUREMENTp12345e67890.csv', parse_dates=['pollTime'])
#-- 1. 取一条心率相关的报警,看阈值与触发值
hr = alarm[alarm['alarmName'].str.contains('Heart Rate', case=False, na=False)]
row = hr.iloc[0]
print(row['pollTime'], row['alarmName'], row['setLow'], row['setHigh'],
row['chanValue'], row['sil'], row['inactivationState'])
#-- 2. 同一时刻附近的测量值
near = meas[(meas['pollTime'] >= row['pollTime'] - pd.Timedelta(seconds=30)) &
(meas['pollTime'] <= row['pollTime'] + pd.Timedelta(seconds=30))]
print(near[['pollTime', 'mesname', 'msite', 'muom', 'mtext']].head(20))
#-- 3. 回到波形:文件名里的时间戳是本地磁盘上的路径
rec = wfdb.rdrecord('p12345e67890d20190512T143000')
print(rec.fs, rec.sig_len, rec.sig_name)
这段流程的意义不在代码本身,而在于它把三种粒度串成了一条链:报警是事件级的,测量是两秒级的,波形是 240 Hz 级的。绝大多数公开数据集只给其中一级,或者给了多级但时间对不上。ALOTT 给的是同一条时间轴上的三级。
需要提醒的是第三步:波形按"连续读取"切段,一次住院会有多个 .hea 文件。定位时刻到文件的映射必须自己按文件名里的时间戳建立索引,官方没有提供一张"时刻—文件"的对照表。
4.4 时间粒度:两秒、240 Hz 与一次住院
三种粒度各有各的用途,也各有各的陷阱。
两秒粒度来自 Bernoulli 系统的输出规范——每个 XML 元素覆盖两秒。它决定了报警与测量的时间分辨率:你不能指望从这两张表里恢复出"哪一秒发生了什么"。对趋势类研究(斜率、累积负荷、昼夜节律)两秒足够;对事件级精确对齐(报警与 QRS 波的先后)两秒太粗,必须回到波形。
240 Hz 是官方举例给出的心电波形采样率,页面上的整体区间是 60–240 Hz。不同通道的采样率可能不同,需要从 .hea 逐条确认。这意味着把多通道波形当作一个等采样率的矩阵来处理是危险的——先读头文件,再决定要不要重采样。
一次住院是最大粒度。它是标签的单位(应急响应事件挂在住院上),也是目录的单位。跨住院的自然连接只有 aMRN,而 aMRN 的日期偏移是每个人独立的,所以同一患者两次住院之间的日历间隔不可用,只有每次住院内部的相对时间可用。
4.5 边界条件:什么情况下它不再适用
| 条件 | 是否适用 | 判断依据 |
|---|---|---|
| 你要研究报警与临床事件的先后顺序 | 适用,且几乎无可替代 | 相对时间完整保留 |
| 你要研究夜间或班次的昼夜模式 | 适用 | 官方明确一天之内的时刻不平移 |
| 你要做年龄分层或儿科研究 | 不适用 | 官方说明未提供年龄,字段为空 |
| 你要按日历季节做分析 | 不适用 | 绝对日期按人随机平移 −180 至 180 天 |
| 你要跨多家医院做外部验证 | 不适用 | 两家医院同属一个医学中心 |
| 你要把报警当作疾病的金标准 | 不适用 | 报警假阳性率高,官方给出每次住院 28,193 条 |
| 你要做开放获取的教学示例 | 不适用 | 受限访问,须签数据使用协议 |
| 你要做跨患者的时间对齐 | 不适用 | 每个 aMRN 的偏移量独立 |
| 你要追逐波形形态学诊断 | 谨慎 | 通道清单与采样率需自行从头文件确认 |
| 你要复现基于综合 ICU 人群的结果 | 谨慎 | 人群为癌症中心与心脏医院 |
这张表最值得记住的是第二行和倒数第三行。第二行是它真正的独占能力:绝大多数去标识数据在抹掉日期的同时也抹掉了时刻,而它保留了时刻,于是"夜里三点发生了什么"仍然可问。倒数第三行则是最容易踩的坑:跨患者对齐看起来只是加一个偏移量的问题,实际上每个患者的偏移量不同且无从得知,任何跨患者的日历级比较都是无效的。
§5 怎么拿到:从申请到可训练张量
5.1 目录结构与下载面
受限访问数据集的目录在未授权状态下不可见——直接访问文件目录会返回 403,官方页面在部分地区还会显示"因法律或政策限制不可用"。因此下面这张表的内容来自官方页面对数据组织的文字描述,而不是来自对目录的实地列举:
| 路径形态 | 内容 | 数量 |
|---|---|---|
allergies.csv 等 |
十张病历仓库平表 | 10 个文件 |
p<aMRN>/ |
患者目录 | 每个 aMRN 一个 |
p<aMRN>/p<aMRN>e<aCSN>/ |
住院目录 | 每个 aCSN 一个 |
.../ALARMp<aMRN>e<aCSN>.csv |
该次住院全部报警 | 每次住院 1 个 |
.../MEASUREMENTp<aMRN>e<aCSN>.csv |
该次住院全部两秒测量 | 每次住院 1 个 |
.../p<aMRN>e<aCSN>d<yyyymmdd>T<hhmmss>.hea |
一段连续波形的头 | 每天每个连续段 1 个 |
.../p<aMRN>e<aCSN>d<yyyymmdd>T<hhmmss><A-Z>.dat |
该段波形数据 | 一个头对应一个或多个 |
| 官方代码仓库 | 转换流水线与示例 Spark 代码 | 仓库见 §9.3 |
官方没有公布全库体积。用"平均每次住院 524,744 个 240 Hz 两秒波形段"这个官方量级去推,单是波形部分就不是个人工作站能一次装下的量级——这跟开放波形库"几十兆到几百兆"的体感完全不同。申请之前先算好存储,是这份数据的第一条工程纪律。
5.2 申请与批量下载
获取路径是三步:注册 PhysioNet 账号 → 完成凭据审核(credentialed access)→ 签署 PhysioNet 受限健康数据使用协议 1.5.0。三步都完成后,文件目录才会对你可见。
拿到权限后,PhysioNet 的标准做法是用账号凭据走 HTTPS:
#-- 1. 在本机保存 PhysioNet 账号(只需一次,权限 600)
echo 'machine physionet.org login <你的用户名> password <你的密码>' > ~/.netrc
chmod 600 ~/.netrc
#-- 2. 递归拉取整个版本目录;受限数据必须带 --user 或 netrc
wget -r -N -c -np --user=<用户名> --ask-password \
https://physionet.org/files/alott/1.0.0/
#-- 3. 只想先拿十张病历表看结构(不碰波形)
wget -r -N -c -np -A '*.csv' --user=<用户名> --ask-password \
https://physionet.org/files/alott/1.0.0/
三点务必注意。其一,受限数据的下载凭据属于个人,不能写进团队共享脚本,也不该进版本库。其二,波形文件数量巨大,先拉 CSV 看结构、再决定要不要拉波形,能省下大量时间与存储。其三,下载下来的数据受数据使用协议约束:不能转发、不能公开、不能搬到未授权的机器上,论文里也不能附上原始数据。
5.3 用 wfdb 读取波形
WFDB 是 PhysioNet 沿用数十年的波形存储规范,头文件是纯文本,数据文件是二进制。波形按连续读取段切开,所以读之前要先建立"时刻到文件"的索引。
import os
import re
import wfdb
BASE = 'alott/1.0.0'
PAT = re.compile(r'p(\d+)e(\d+)d(\d{8})T(\d{6})') #-- 从文件名解析 aMRN/aCSN/日期/时刻
def index_hea(root):
#-- 扫描全部 .hea,返回 [(aMRN, aCSN, 起始时刻串, 路径)]
out = []
for dirpath, _, files in os.walk(root):
for f in files:
if f.endswith('.hea'):
m = PAT.match(f)
if m:
out.append((m.group(1), m.group(2), m.group(3) + m.group(4),
os.path.join(dirpath, f[:-4])))
return sorted(out, key=lambda r: (r[0], r[1], r[2]))
idx = index_hea(BASE)
print(len(idx), idx[0])
#-- 读第一段;sig_name 与 fs 才是通道清单与真实采样率的来源
rec = wfdb.rdrecord(idx[0][3])
print('采样率', rec.fs, '采样点', rec.sig_len, '通道', rec.sig_name)
print(rec.p_signal.shape) #-- 已按头文件增益换算为物理量
这段代码里最容易被忽略的是最后两行:官方页面给的是 60–240 Hz 这个区间,真正的采样率与通道名只在头文件里。把它们硬编码成 240 Hz 或固定通道顺序,是这份数据上最常见的错误。
5.4 转成通用的表结构
波形之外的数据本来就是 CSV,用 pandas 直接读即可;真正的工程任务是把三张遥测表与十张病历表按时间对齐。
import pandas as pd
adm = pd.read_csv('admissions.csv', parse_dates=['admitTime', 'dischargeTime'])
flow = pd.read_csv('flowsheet.csv', parse_dates=['pollTime'])
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'])
#-- 以住院为单位计算相对时间:入院时刻为零点
a = adm[adm['aCSN'] == 67890].iloc[0]
t0 = a['admitTime']
flow['rel_hour'] = (flow['pollTime'] - t0).dt.total_seconds() / 3600.0
alarm['rel_hour'] = (alarm['pollTime'] - t0).dt.total_seconds() / 3600.0
#-- 应急响应事件在流程表里,靠记录类型字段区分;口径必须写进方法节
ert = flow[flow['<类型字段>'].astype(str).str.contains('ERT', case=False, na=False)]
print(ert['rel_hour'].describe())
这段代码里有一处必须你自己填:官方页面只说流程表"包含生命体征、风险评分与应急响应事件",没有给出区分它们的字段名与取值。真实字段名与取值要到数据字典或实际文件里确认,不能照抄上面的示意写法。这也是本数据集的一个现实:官方文档给了表级语义,字段级字典指向外部仓库。
5.5 报警与测量的读取
报警表与测量表都是两秒粒度、按次住院单文件,体量不小但结构极简。读的时候有两个习惯值得养成:
import pandas as pd
dtype_map = {'alarmName': 'string', 'abnormalFlags': 'string',
'inactivationState': 'string'}
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'],
dtype=dtype_map, low_memory=False)
#-- 静音与停用是两条不同的信息,别混为一谈
print('报警总数', len(alarm))
print('被静音', int((alarm['sil'] == 1).sum()))
print('停用状态取值', alarm['inactivationState'].dropna().unique()[:10])
#-- 测量值以文本存储,使用前必须转数值并核对单位
meas = pd.read_csv('MEASUREMENTp12345e67890.csv', parse_dates=['pollTime'])
meas['value'] = pd.to_numeric(meas['mtext'], errors='coerce')
print(meas.groupby(['mesname', 'muom'])['value'].count().head(20))
sil 与 inactivationState 的区别值得单独说清:前者是这一次报警响了但被人按掉了,后者是这个报警压根被关掉了。研究报警疲劳时两者含义相反——静音说明有人听见了并判断不重要,停用说明它从来没机会响。把它们并成一个"未响应"变量是错的。
5.6 五个最容易出错的地方
| 位置 | 错误写法 | 后果 | 正确做法 |
|---|---|---|---|
| 时间对齐 | 直接用绝对日期比较不同患者 | 每个 aMRN 偏移量独立,跨患者日历比较无效 | 只在住院内部用相对时间 |
| 昼夜分析 | 认为时刻也被平移了 | 会误以为做不了昼夜研究 | 官方明确一天之内的时刻不平移 |
| 波形读取 | 把采样率当成 240 Hz 硬编码 | 官方给的是 60–240 Hz 区间 | 每个 .hea 单独读 fs 与 sig_name |
| 波形拼接 | 按文件名排序后直接顺序拼接 | 中间可能有监护中断造成的缺口 | 用时间戳算间隔,缺口显式补齐或保留 |
| 标签定义 | 把报警当作恶化事件 | 报警假阳性率高,会污染标签 | 用流程表中的应急响应事件,并写明口径 |
| 人群描述 | 用年龄、种族做分层 | 官方未提供年龄 | 分层改用住院时长、ICU 与否等可得变量 |
| 合规 | 把数据拷到未授权机器或公开仓库 | 违反数据使用协议 | 全程在签署协议的受控环境内处理 |
这张表的最后一行不是技术建议,是使用前提。受限健康数据的约束贯穿整个生命周期:从下载、存储、处理到论文发表后的数据留存,每一步都在协议范围内。
§6 与库内条目的关系
6.1 关系图谱
在重症与生理信号这一类目里,可以用"数据形态 × 时间保真度"两个轴把相关数据集摆开:
| 站内数据集 | 主要形态 | 时间保真度 | 与 ALOTT 的关系 |
|---|---|---|---|
| 巴塞罗那 SICU 信号集 | 床旁监护波形与临床变量 | 相对时间保留 | 最接近的同类:同为床旁监护,但规模与病历深度不同 |
| CHARIS 颅内压监护波形库 | 重症波形多通道 | 相对时间保留 | 互补:它给神经重症的通道组合,ALOTT 给遥测加病历 |
| AAMI EC13 测试波形 | 标准测试波形 | 不适用 | 对照:它定义报警正确性标准,ALOTT 给真实报警流水 |
| HCUP 住院数据家族 | 住院与理赔 | 时间粗 | 对照:它有住院规模但无波形与相对时间 |
| KNHANES 国民健康调查 | 调查与检查 | 时间粗 | 对照:人群级,无连续性 |
| INCART 心律失常库 | 十二导联长时程心电 | 相对时间保留 | 对照:波形精细但无病历上下文 |
| CPAP 流量压力集 | 呼吸机波形 | 相对时间保留 | 互补:呼吸支持侧的波形细粒度样本 |
| BIDMC 心衰库 | 长时程心电与呼吸 | 相对时间保留 | 对照:单病种、无病历表 |
| 自主神经衰老心肺库 | 静息心肺信号 | 相对时间保留 | 对照:健康人群、短时程、无病历 |
| MIT-BIH 长时程心电库 | 长时程心电与标注 | 相对时间保留 | 对照:标注精细但人群与场景完全不同 |
| 爱沙尼亚生物样本库 | 电子健康记录与组学 | 时间粗 | 对照:病历与组学深,但无连续波形 |
这张表要说清的是位置:ALOTT 坐在"波形精细 + 病历完整 + 相对时间保留"这三者的交集上。单看任何一维都有更强的对手,三维同时成立的很少。
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 同为床旁监护的波形资源 | SICU、bedside monitor、重症监护 |
§6.1 第一行 |
| 报警的标准与正确性 | AAMI EC13、alarm、监护仪报警 |
§6.1 第三行 |
| 住院级别的病历与理赔 | HCUP、住院、电子健康记录 |
§6.1 第四行 |
| 波形精细但无病历的对照 | MIT-BIH、心律失常、长时程 |
§2.6 与 §6.1 |
| 相对时间被抹除的病历库 | MIMIC、去标识 |
§1.1 与 §4.1 |
| 呼吸支持相关波形 | CPAP、ventilator、呼吸机 |
§1.3 与 §6.1 |
6.3 与其他库的分工判据
| 任务 | 主粮仓该用什么 | ALOTT 的位置 | 原因 |
|---|---|---|---|
| 恶化预警模型的预训练 | 大规模重症电子病历库 | 外部测试或补充 | 单中心、两家专科医院 |
| 报警负担与报警疲劳研究 | 无可替代 | 主力 | 真实报警流水含静音与停用状态 |
| 报警与波形的互相印证 | 无可替代 | 主力 | 两套数据时间可对齐 |
| 昼夜节律与班次效应 | 少数可用者之一 | 主力之一 | 一天之内的时刻不平移 |
| 波形形态学诊断模型 | 标注完备的心电或脑电库 | 不适用 | 无形态学标注 |
| 儿科或年龄分层研究 | 含年龄的队列库 | 不适用 | 官方未提供年龄 |
| 开放获取的教学示例 | 开放波形库 | 不适用 | 受限访问 |
| 多中心泛化验证 | 多中心库 | 不适用 | 单一医学中心 |
| 数据脱敏流水线参考 | 官方代码仓库 | 主力 | 转换代码公开,含日期偏移与映射表删除 |
被高估的用法是第一行——把它当预警模型的主训练库。它在形态上确实像重症病历库,但人群是肿瘤与心脏专科住院患者,且官方自称试点项目。被低估的用法是第三行与第四行:这两件事在别处基本做不了。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先纠正一个常见的误判:把"没有人工标注"当成"质量差"。ALOTT 记录的不是研究者判读出来的结论,而是临床流程里真实留下的痕迹——监护仪真的响了,护士真的记了,应急响应团队真的被叫了。这类数据的价值在于"真",代价在于"脏":录入有遗漏、报警有假阳性、匹配有误差,而且这些误差都不可回溯。
评价它应当问的是:在它能回答的那个问题上,这些痕迹够不够真实、够不够密?而不是:它有没有一个干净的标签列。
7.1 五维评分
按 DAIMS 的常用维度打分,每项 1–5 分,分数针对"作为床旁监护与恶化预警研究数据"这个用途:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 4 | 270 张病床、15,000 余次住院,遥测粒度极密 |
| 标注质量 | 2 | 无人工标注,标签来自流程表,无复核、无一致性检验 |
| 任务适配 | 5 | 报警、波形、病历、相对时间四项交集,几乎无替代 |
| 文档完整 | 3 | 表级语义清楚,字段级字典指向外部仓库,目录不可见 |
| 可获取性 | 2 | 受限访问,须注册、审核、签协议,部分地区不可获取 |
五项合计 16 分(满分 25)。这个分数结构说明它是一件"有门槛的专用工具":规模与适配性突出,标注与可获取性拖后腿。想用它的人要先确认自己确实需要那个交集,否则门槛不划算。
7.2 时间保真的两层
第一层是住院内部的时间,这是它的强项。相对时间完整保留,一天之内的时刻不平移,因此可以问"报警之后多久叫来了应急响应团队"“夜里的报警密度是否更高”。
第二层是跨住院与跨患者的时间,这是它的弱项。每个 aMRN 有独立的随机偏移,偏移量在 −180 到 180 天之间,且映射表已被删除。同一患者的两次住院之间隔着多少天,无从得知;不同患者的"住院第三天"不在同一个日历上。
| 用法 | 时间保真度的影响 | 建议 |
|---|---|---|
| 住院内部的事件先后 | 完全可靠 | 直接用相对时间 |
| 昼夜节律与班次 | 可靠 | 时刻未平移,可直接用 |
| 同一患者的多次住院间隔 | 不可用 | 不要做再入院时间间隔分析 |
| 跨患者的日历对齐 | 不可用 | 不要做同期比较 |
| 季节性疾病模式 | 基本不可用 | 偏移量虽有限但方向随机 |
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 人群专科化 | 一家综合癌症中心与一家心脏医院 | 结果不能外推到普通内科或外科病房 |
| 单中心 | 两家医院同属一个医学中心 | 设备、录入规范、呼叫标准都单一 |
| 年龄缺失 | 诚实经纪人未提供年龄,字段为空 | 一切年龄分层研究做不了 |
| 患者数未公布 | 只给病床数与住院次数 | 无法报告去重患者数,样本描述不完整 |
| 标签来自流程 | 应急响应事件是流程记录而非人工判读 | 标签完整性与一致性未知 |
| 匹配不可回溯 | 映射表在日期平移后被删除 | 无法识别靠位置推断出来的匹配 |
| 报警本身噪声大 | 平均每次住院 28,193 条报警 | 把报警当结局会被假阳性淹没 |
| 采集随临床流程中断 | 转床、检查、关机都会断流 | 波形缺口不是随机缺失 |
| 官方自述为试点 | 摘要首句即称 pilot project | 规模与覆盖面可能不代表最终形态 |
| 页面自述不一致 | 摘要写 26 个月收录窗口,页面摘要描述写作 9 个月 | 收录时长存在两种说法,需以摘要正文为准 |
最后一行值得单独说明:官方页面的元描述把数据集写成"9 个月的去标识高分辨率遥测",而摘要正文写的是 2018 年 9 月至 2020 年 11 月。两者不一致,官方没有解释。正式引用时以摘要正文的窗口为准,并在方法节注明这一点。
7.4 外部验证矩阵
由于数据集 2025 年 3 月才上线,且为受限访问,公开文献中直接以它为对象的实证研究还很少。下面这张表描述的是"可以怎么用它做验证",而不是"已经有人这样做过":
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 作为单中心外测集 | 在大型重症病历库上训练,在本库上外测 | 人群与设备不同,能读出泛化差 | 掉分幅度里混着人群差异与录入规范差异 |
| 作为报警研究的唯一场 | 直接在本库上研究报警负担 | 字段齐全,含静音与停用 | 命名规范未保证统一 |
| 作为波形—病历对齐方法的基准 | 验证自己的对齐算法 | 官方映射已固化,可作为参照 | 官方映射本身不可回溯 |
| 作为脱敏流水线的参考实现 | 复现官方的日期偏移与主键掩码 | 代码公开 | 需要本机构的伦理与合规审查 |
这里要给出一个明确的判断:把它当"说不"的工具比当"说好"的工具更有价值。如果你的预警模型在本库上掉得很厉害,那说明它在原库上的成绩里有一部分来自记住那家医院的录入习惯与设备特性;如果掉得不多,才值得进一步讨论泛化能力。反过来,也不要把本库上的成绩当作绝对标准——人群、标签口径、缺失模式都不同,跨论文比较绝对数值没有意义。
7.5 它为何值得关注:稀缺的是"同时具备",不是"某一项更强"
波形库很多,病历库很多,报警数据几乎没有,能把三者按时间对齐的更少。ALOTT 的价值不在于任何单独一项做到了极致,而在于它同时具备四项,并且明确为"时序模式研究"而设计。只要这个组合仍然稀缺,它就值得被记住——即使它只是一个试点项目、只有一个版本、且在获取上有不小的门槛。
§8 生态位与历史
8.1 历史沿革
ALOTT 的起点不是数据共享,而是临床信息学的一个具体问题。官方在背景里引用的人因工程文献指出:实践者用来预判病情恶化的那组早期征象,往往是微弱且非特异的,而现有监护技术提供的信息与临床决策真正需要的信息之间存在缺口。这个判断把项目引向了"记录真实流程"而不是"采集研究数据"。
2013 与 2019 两个机构审查委员会批件说明项目筹备期很长;2018 年 OSU 与 GE 启动全病床遥测落盘;2023 年转换代码以预发布形式在 Zenodo 存档(DOI 10.5281/zenodo.7922122);2025 年 3 月 19 日数据本体以 1.0.0 版本在 PhysioNet 上线。代码先于数据公开,是这个项目的一个特点——它希望别人能照着这条流水线在自己的机构复现一遍。
8.2 与重症病历系谱的关系
官方在背景里直接把 MIMIC-III 举作同类,也直接点出了它的不足:多数这类遥测—病历数据集不保留患者事件的时间。ALOTT 的定位因此可以读作"MIMIC 系谱上的一个补丁"——不是要替代它,而是要补上被隐私处理抹掉的那一个维度。
它也明确列出了四条发布目标:让研究者用它改善医疗结局;通过主体间可验证性提升现有算法的严谨度;鼓励基于公开且有良好文档的数据集做透明可复现的研究;为其他机构如何从自己的患者人群生成同构数据集提供样板。第四条尤其值得注意——它把"方法论的示范"写进了数据集的目标里,这在数据发布里不多见。
8.3 生态位:专用工具而不是通用粮仓
| 角色 | 通用粮仓 | 专用工具 |
|---|---|---|
| 典型用法 | 大规模训练、预训练、基准排名 | 特定机制研究、方法学验证、对照实验 |
| 需要的前提 | 数据量大、标签干净 | 某一维度的独占性 |
| 代表 | 大型重症病历库、大型标注波形库 | ALOTT 遥测病历库、标准测试波形集 |
| 失败模式 | 标签噪声累积、人群偏斜 | 门槛高于收益、结论样本量不足 |
ALOTT 坐在右边这一列。把它当通用粮仓用,会先被获取门槛拦一道,再被人群专科化与标签噪声拦一道;把它当专用工具用,它的独占维度立刻兑现。
8.4 谁会用它,用来做什么
从数据集的设计目标与字段构成推断,潜在用户集中在三类:做病情恶化与应急响应预测的临床信息学组(用流程表与遥测做时序建模)、做患者安全与人因工程的研究组(用报警流水研究报警疲劳与报警设置)、做医疗数据工程的团队(照着公开的转换流水线建自己的版本)。第三类可能是作者最希望的——他们在背景里明写了一条目标是给其他机构做样板。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 临床信息学研究者 | 读官方页面的数据描述段,申请权限 | 拉十张病历表,确认应急响应事件的字段口径 | 标签口径必须写进方法节 |
| 患者安全与人因研究者 | 读报警表字段定义 | 按报警名称归并,统计静音与停用 | 命名规范未保证统一,先做归并表 |
| 医疗数据工程团队 | 读官方代码仓库的转换流水线 | 复现日期偏移与主键掩码两步 | 伦理与合规审查要在本地先过 |
9.2 一条最短的可用流程
#-- 1. 拿到权限后先只拉十张病历表,确认结构与字段名
wget -r -N -c -np -A '*.csv' --user=<用户名> --ask-password \
https://physionet.org/files/alott/1.0.0/
#-- 2. 列出某次住院的报警与测量文件,确认命名规则
ls p12345/p12345e67890/ | head
#-- 3. 统计该次住院的 .hea 数量,估算波形段数与存储
ls p12345/p12345e67890/*.hea | wc -l
import pandas as pd
#-- 以入院时刻为零点,把报警与流程表投到同一条相对时间轴上
adm = pd.read_csv('admissions.csv', parse_dates=['admitTime'])
t0 = adm.set_index('aCSN')['admitTime']
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'])
alarm['rel_h'] = (alarm['pollTime'] - t0.loc[67890]).dt.total_seconds() / 3600.0
flow = pd.read_csv('flowsheet.csv', parse_dates=['pollTime'])
flow = flow[flow['aCSN'] == 67890].copy()
flow['rel_h'] = (flow['pollTime'] - t0.loc[67890]).dt.total_seconds() / 3600.0
#-- 按小时对齐:先确认流程表里区分应急响应事件的字段名再筛选
print(alarm['rel_h'].min(), alarm['rel_h'].max())
print(flow['rel_h'].min(), flow['rel_h'].max())
上面第二步里的目录名只是示意,真实 aMRN 与 aCSN 需要从病历表里读出来。整个流程真正需要你先做的一件事是:把流程表里"哪一行是应急响应事件"这件事确认清楚,否则后面所有的时间对齐都没有意义。
9.3 引用方式
PhysioNet 的惯例是引用数据集本身加平台:
| 引用对象 | 内容 |
|---|---|
| 数据集 | Lawrence, J., Rayo, M., & Huerta, T. (2025). ALarms, Outcomes Telemetry with Timing (ALOTT): a Bedside-EMR Database (version 1.0.0). PhysioNet. https://doi.org/10.13026/sbq5-dy17 |
| 平台 | PhysioNet 平台综述论文(2026 年发表于 Nature Health),按官方页面的 Cite 按钮生成 |
| 平台标识符 | RRID:SCR_007345 |
| 代码仓库 | https://github.com/johnclawrence/Carescape |
| 最新 DOI | 10.13026/46e5-hh23 |
写论文时建议同时注明:使用的版本号(1.0.0)、应急响应事件的判定口径、以及是否使用了波形部分。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑把关结构与事实 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与官方给出的代码仓库描述 |
| 文件核验 | 文件目录在受限访问状态下返回 403,未能实地列举;目录结构、文件命名与字段清单均来自官方页面的文字描述 |
| 不一致说明 | 官方页面元描述写"9 个月",摘要正文写 2018 年 9 月至 2020 年 11 月,两者不一致,正文以摘要为准并已标注 |
| 论文信息 | 未检索到以该数据集为对象的公开实证研究全文,§7.4 只描述可用法而非既有结果 |
| 未核验内容 | 去重患者数、波形通道清单与逐通道采样率、全库体积、流程表中区分应急响应事件的字段名与取值、各报警名称的取值集合、"每次住院平均"五项数字的统计口径 |
| 图像 | 无配图;封面为生成式提示词,不含真实波形或病历 |
| 免责 | 本文不构成临床建议;数据使用须遵守 PhysioNet 受限健康数据使用协议 1.5.0 与许可 1.5.0 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它可以像开放数据集一样直接下载」 | 受限访问,须注册、通过凭据审核并签署数据使用协议 1.5.0 | 官方页面标注 Restricted Access,未授权访问文件目录返回 403 |
| 「它是另一个 MIMIC」 | 人群不同、机构单一、无综合 ICU 混合人群,官方定位是补上时间维度 | 官方背景明确点出 MIMIC-III 不保留事件时间 |
| 「它有年龄,可以做年龄分层」 | 诚实经纪人未提供年龄,该字段不是已填充变量 | 官方去标识章节原话 |
| 「15,000 就是患者数」 | 15,000 是住院次数,去重患者数官方未公布 | 摘要写 over 15,000 hospital admissions |
| 「日期被随机化了,所以昼夜节律也做不了」 | 一天之内的时刻不平移,昼夜与班次研究可行 | 官方写明日期平移而时刻不平移 |
| 「跨患者的住院日期可以放在一起比」 | 每个 aMRN 有独立的随机偏移,跨患者日历比较无效 | 官方说明偏移量为每患者 −180 至 180 天 |
| 「报警就是恶化事件,可以直接当标签」 | 报警假阳性率高,官方给出平均每次住院 28,193 条 | 报警量与临床常识一致,结局应取流程表中的应急响应事件 |
| 「波形全是 240 Hz」 | 官方给的是 60–240 Hz 区间,240 Hz 是心电波形的举例 | 官方摘要与遥测采集章节 |
| 「收录窗口是 9 个月」 | 摘要正文写 2018 年 9 月至 2020 年 11 月;页面元描述写 9 个月,两者不一致 | 官方摘要正文与页面元描述 |
| 「它有人工判读的金标准标注」 | 无人工标注,事件为监护仪与护理流程表的原生记录 | 官方数据描述段未提及任何人工标注环节 |
FAQ
Q1:ALOTT 到底有多少患者?
官方没有公布。摘要给的是两个规模数字:270 张病床与超过 15,000 次住院。患者以 aMRN 掩码标识,但去重后的患者人数不在页面上,也不在数据描述段里。写论文时需要报告人群规模的话,只能报告病床数与住院次数,并把"去重患者数未公布"写进局限性。
Q2:为什么它敢保留相对时间,别的数据集不敢?
因为它把风险拆成了两半分别处理。绝对日期被按患者整体平移 −180 到 180 天,消除了日历上的可追溯性;住院内部的相对时间与一天之内的时刻完整保留,这两项不足以单独识别到个人,却足以支撑时序研究。多数同类数据集选择整体抹掉时间,是更保守的一种取舍,代价是时序问题全部无法回答。
Q3:没有年龄,研究还能做吗?
能做,但要换分层变量。可用的分层维度包括:是否入住 ICU(ICU 表)、住院时长与 ICU 停留时长(admissions 表与官方给出的中位值)、所在床位与病区(location 表)、主要与次要诊断(admissions 表)。不能用年龄做的那部分结论,要老实写进局限性,不要用别的变量冒充年龄效应。
Q4:报警表里的 sil 和 inactivationState 有什么差别?
sil 等于 1 表示这一次报警响了、但被人按掉了;inactivationState 表示这个报警处于停用状态,压根不会响。研究报警疲劳时两者方向相反:静音意味着有人听见并判断不重要,停用意味着它从没机会被听见。把它们合并成"未被响应"是错误的。
Q5:波形怎么定位到某一次报警发生的时刻?
官方没有提供"时刻—文件"对照表。波形按连续读取段切分,文件名里带起始日期与起始时刻,需要自己扫描全部 .hea、按文件名解析出时间戳建索引,再根据报警时刻二分查找落点。注意段与段之间可能有监护中断造成的缺口,拼接时要显式处理,不能直接按文件名顺序首尾相连。
Q6:它和开放获取的波形库相比,获取成本高在哪?
三步:注册 PhysioNet 账号、通过凭据审核、签署受限健康数据使用协议 1.5.0。之后还有持续义务——数据不能转发、不能公开、不能搬到未授权的机器上,处理环境要符合协议里的安全标准。部分地区还会因法律或政策原因完全不可获取。
Q7:官方给出的"平均每次住院"那五个数字能用吗?
当量级指示用是安全的,当精确期望值用不安全。官方把它们写作每次住院的平均,但同一页给出的中位住院时长是 69 小时、中位 ICU 停留是 128 小时,两组数字放在一起量级并不自洽,官方也没有说明这些均值是按每次住院、每床日还是别的口径统计。用它估算存储与算力可以,写进样本量计算不行。
Q8:它的许可允许什么、禁止什么?
适用 PhysioNet 受限健康数据许可 1.5.0 与同名的数据使用协议 1.5.0。允许的是在协议约定的安全环境内做研究;禁止的是尝试识别个体患者、转发或公开数据、在未授权环境处理。商业使用与二次发布的边界以协议全文为准,不要凭开放数据许可的常识推断。
术语表
| 术语 | 解释 |
|---|---|
| 遥测监护 | 床旁监护仪对住院患者的连续生理监测,数据按设备时钟输出 |
| 诚实经纪人 | 机构内负责在研究者与患者数据之间执行去标识与合规审核的中介角色 |
| aMRN | 掩码后的患者标识符,由病历号映射为不重复的随机整数 |
| aCSN | 掩码后的就诊标识符,由接触序列号映射为不重复的随机整数 |
| 日期平移 | 把每位患者的全部日期统一加上一个随机偏移,保留相对关系、模糊绝对日期 |
| WFDB | PhysioNet 使用的波形数据库格式,由文本头文件与二进制数据文件组成 |
.hea |
WFDB 的文本头文件,声明采样率、通道名、增益与基线 |
.dat |
WFDB 的二进制信号文件 |
| 报警静音 | 报警触发后被人工按掉,记为 sil = 1 |
| 报警停用 | 报警被关闭,该时段内不会触发,记在 inactivationState |
| 应急响应团队 | 院内针对患者病情急剧恶化启动的快速反应小组,简称 ERT |
| 护理流程表 | 护士录入的带时间戳记录,含生命体征、风险评分与应急响应事件 |
| 受限访问 | 须注册、通过审核并签署数据使用协议后才能获取的数据访问级别 |
| 数据使用协议 | 规定数据可如何使用、禁止何种行为的法律文件,简称 DUA |
附录 A:核心数字核对表
| 项 | 值 | 来源层级 |
|---|---|---|
| 病床数 | 270 张 | 官方页面摘要 |
| 住院次数 | 超过 15,000 次 | 官方页面摘要 |
| 时间跨度 | 2018 年 9 月至 2020 年 11 月 | 官方页面摘要 |
| 波形采样率 | 60–240 Hz | 官方页面摘要 |
| 心电波形采样率举例 | 240 Hz | 官方页面遥测采集章节 |
| 非波形测量粒度 | 两秒 | 官方页面摘要与方法章节 |
| XML 单文件覆盖时长 | 最多 30 分钟,内部按两秒切分 | 官方页面遥测采集章节 |
| 病历表数量 | 10 张 CSV | 官方页面数据描述段 |
| 平均每次住院护理记录 | 779 条 | 官方页面方法章节 |
| 平均每次住院实验室测量 | 266 条 | 官方页面方法章节 |
| 平均每次住院遥测报警 | 28,193 条 | 官方页面方法章节 |
| 平均每次住院波形段 | 524,744 段(240 Hz、两秒) | 官方页面方法章节 |
| 平均每次住院遥测测量 | 1,020,071 条 | 官方页面方法章节 |
| 日期偏移范围 | −180 至 180 天 | 官方页面去标识章节 |
| 中位住院时长 | 69 小时 | 官方页面方法章节 |
| 中位 ICU 停留时长 | 128 小时 | 官方页面方法章节 |
| 男性比例 | 57.8% | 官方页面方法章节 |
| 版本与发布日期 | 1.0.0,2025 年 3 月 19 日 | 官方页面版本历史 |
| 许可 | PhysioNet 受限健康数据许可 1.5.0 | 官方页面 Access 区 |
| 数据使用协议 | PhysioNet 受限健康数据使用协议 1.5.0 | 官方页面 Access 区 |
| DOI(v1.0.0) | 10.13026/sbq5-dy17 | 官方页面 Discovery 区 |
| DOI(latest) | 10.13026/46e5-hh23 | 官方页面 Discovery 区 |
| 伦理批件 | IRB 2013H0419、2019H0058 | 官方页面伦理章节 |
| 年龄字段 | 未提供,非已填充变量 | 官方页面去标识章节 |
| 去重患者数 | 未公布 | 官方页面未出现,列入未核验 |
附录 B:数字的来源分层
第一层:官方页面正文。 病床数、住院次数、时间跨度、采样率区间、两秒粒度、十张病历表、五项每次住院均值、中位住院时长与中位 ICU 停留时长、男性比例、日期偏移范围、版本与日期、许可与协议、DOI、伦理批件。
第二层:官方页面指向的外部资源。 代码仓库、Zenodo 上 2023 年的预发布代码存档、平台综述论文,只用于说明来源与引用方式。
第三层:未核实。 去重患者数、逐通道采样率、全库体积、应急响应事件的字段名与取值、五项均值的统计口径。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | ALOTT v1.0.0 官方页面 | https://physionet.org/content/alott/1.0.0/ | 全部规模、结构、边界数字 |
| 2 | ALOTT 文件目录(受限,未授权返回 403) | https://physionet.org/files/alott/1.0.0/ | 目录结构未能实地核验 |
| 3 | Carescape 代码仓库 | https://github.com/johnclawrence/Carescape | 转换流水线与字段级字典入口 |
| 5 | PhysioNet 平台综述(2026,Nature Health) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 6 | WFDB Python 软件包(官方引用 [6]) | https://doi.org/10.13026/9njx-6322 | 波形读写方式与版本 |
| 8 | 人因工程与恶化识别相关文献(官方引用 [1]–[4]) | 见官方页面 References 段 | 研究背景与动机 |
附录 D:任务代码
任务一:建立"时刻—波形文件"索引并核对一条报警
import os
import re
import wfdb
import pandas as pd
#-- 文件名形如 p12345e67890d20190512T143000.hea
PAT = re.compile(r'p(\d+)e(\d+)d(\d{8})T(\d{6})')
def build_index(root):
#-- 返回 [(aMRN, aCSN, 起始时刻串, 去扩展名路径)]
out = []
for dp, _, fs in os.walk(root):
for f in fs:
if f.endswith('.hea'):
m = PAT.match(f)
if m:
out.append((m.group(1), m.group(2),
m.group(3) + m.group(4),
os.path.join(dp, f[:-4])))
return sorted(out, key=lambda r: (r[0], r[1], r[2]))
idx = build_index('alott/1.0.0')
#-- 报警时刻落到哪一段波形:按起始时刻串二分查找
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'])
t = alarm.iloc[0]['pollTime'].strftime('%Y%m%d%H%M%S')
cand = [r for r in idx if r[0] == '12345' and r[1] == '67890']
print('该次住院波形段数', len(cand))
print('落点候选', [r[2] for r in cand if r[2] <= t][-3:])
#-- 打开最后一段,确认真实采样率与通道名
rec = wfdb.rdrecord(cand[-1][3])
print(rec.fs, rec.sig_name)
任务二:把报警与流程表投到同一条相对时间轴上
import pandas as pd
adm = pd.read_csv('admissions.csv', parse_dates=['admitTime'])
t0 = adm.set_index('aCSN')['admitTime']
alarm = pd.read_csv('ALARMp12345e67890.csv', parse_dates=['pollTime'])
flow = pd.read_csv('flowsheet.csv', parse_dates=['pollTime'])
for df in (alarm, flow):
df['rel_h'] = (df['pollTime'] - t0.loc[67890]).dt.total_seconds() / 3600.0
#-- 应急响应事件藏在流程表里,字段名与取值必须先确认
ert = flow[flow['<类型字段>'].astype(str).str.contains('ERT', case=False, na=False)]
#-- 只保留住院窗口内的记录
span = (adm.loc[adm['aCSN'] == 67890, 'LOS hours'].iloc[0])
print('住院窗口小时数', span)
print('报警相对时间范围', alarm['rel_h'].min(), alarm['rel_h'].max())
print('应急响应事件时刻', sorted(ert['rel_h'].round(2).tolist())[:20])
第二段代码里有两个需要你填的地方:流程表里区分事件类型的字段名,以及住院时长字段的确切列名。这两项都不在官方页面的文字描述里,必须从实际文件或仓库的数据字典确认。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 270 张病床、15,000 余次住院、2018 年 9 月至 2020 年 11 月 | 这三个数字定义了它的规模与时间边界 |
| 2 | 保留相对时间、平移绝对日期、时刻不平移 | 这是它与其他去标识病历数据集最本质的区别 |
| 3 | 十张病历表加遥测三件套,靠 aMRN 与 aCSN 连接 | 决定了所有分析的组织方式 |
| 4 | 没有年龄,没有人工标注,患者数未公布 | 这三项决定了哪些研究做不了 |
| 5 | 受限访问,须签数据使用协议 1.5.0 | 决定了它与开放数据集完全不同的获取成本 |
编辑说明
本文的核验时间为 2026 年 10 月 28 日。核对方式为直接访问 PhysioNet 项目主页,逐段确认摘要、背景、方法、数据描述、使用说明、发布说明、伦理与参考文献各段的表述;版本历史、Access 区、Discovery 区与项目浏览计数同样来自该页。文件目录在受限访问状态下返回 403,未能实地列举,因此目录结构、文件命名规则与字段清单均引自官方页面的文字描述,而非对文件的直接观察;这一点已在 §10 的声明表中写明。
两处官方自述不一致已在正文标明:其一,页面元描述把收录窗口写成 9 个月,而摘要正文写的是 2018 年 9 月至 2020 年 11 月,正文取后者;其二,官方给出的五项"平均每次住院"数字与同页的中位住院时长在量级上不自洽,统计口径未说明,正文只用其作量级指示并列入未核验。
未覆盖的内容包括:去重患者数、逐通道采样率、全库体积、应急响应事件的字段名与取值、以及遥测与病历匹配的准确程度。这些需要拿到授权后实地统计,本文按要求只写规模、结构、边界三类数字。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- sicdb — 共享标签:生理信号 / 重症监护 / 电子健康记录 / 时序数据
- ctu-uhb-ctg — 共享标签:生理信号 / 重症监护 / 电子健康记录 / 时序数据
- hirid — 共享标签:重症监护 / 电子健康记录 / 时序数据
- eicu-collaborative-legacy — 共享标签:重症监护 / 电子健康记录 / 时序数据
- mimic-iv-waveform-legacy — 共享标签:生理信号 / 重症监护 / 时序数据
- mimic-iv-ed-legacy — 共享标签:重症监护 / 电子健康记录 / 时序数据
- mimic-iv-ed — 共享标签:重症监护 / 电子健康记录 / 时序数据
- barcelona-sicu-signals — 共享标签:生理信号 / 重症监护 / 电子健康记录
- osv — 共享标签:生理信号 / 电子健康记录 / 时序数据
- cinc-2015 — 共享标签:生理信号 / 重症监护 / 电子健康记录 / 时序数据
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

