信息速览
三名研究者在一九九九年把一个简单的念头写成了论文:三岁孩子的步态看起来已经和成人差不多,但步态节律背后的控制是否也已经成熟。要回答这个问题,不需要更精密的传感器,只需要足够多的孩子、足够长的一段连续行走,以及把每一步的间隔逐个记下来的耐心。Gait Maturation Database 就是这次测量的存档——五十名健康儿童,年龄从四十个月到一百六十三个月,每人一段连续行走,逐拍时长被切成两列文本留给后来的人。
这条线索在今天仍有一个不太显眼的价值:它是少数几个「健康儿童、纯发育、无疾病标签」的公开步态节律库。多数儿科步态数据是为了诊断某种疾病而收集的,健康对照只是陪衬;这一份相反,全部是健康儿童,疾病信息从设计上就不存在。于是它可以被当作一个干净的参照面,用来回答「什么算正常」这类问题,而不是「怎么区分病人」。
库的授权是 ODC 署名 1.0,下载无需注册,整包不足两兆字节。结构极简:五十个文本文件、五十个 WFDB 头文件、五十个一字节步幅序列、一张五十行的人口学表,再无别的。下文按「它要解决什么麻烦、数据长什么样、和同门三个库怎么分工、怎么把它读进内存」的顺序展开,一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 官方全名 | Gait Maturation Database |
| 发布平台 | PhysioNet(MIT Laboratory for Computational Physiology 维护) |
| 版本与日期 | 1.0.0,1999 年 10 月 28 日发布,此后无更新 |
| DOI | 10.13026/C2H014 |
| 署名作者 | Jeffrey Hausdorff(Beth Israel Hospital)、Chung-Kang Peng(Harvard Medical School) |
| 引用论文 | Hausdorff、Zemany、Peng、Goldberger,J Appl Physiol 86:1040-1047,1999 |
| 研究问题 | 三岁以后步态节律的动力学是否仍在发育 |
| 受试者 | 50 名健康儿童,男女各 25 名 |
| 年龄跨度 | 40 至 163 个月(官方页面口径) |
| 记录数 | 50 条,每条三份派生物 |
| 每段时长 | 约八分钟连续行走,官方未逐条公布 |
| 采样率声明 | 250 Hz,见于 WFDB 头文件 |
| 发布内容 | 逐拍时长序列 + 人口学表,不含原始足底波形 |
| 未压缩体积 | 1.4 MB |
| 许可 | Open Data Commons Attribution License v1.0 |
| 疾病标签 | 无,全部为健康儿童 |
§1 它要解决的具体麻烦
1.1 干净的儿科节律参照面很少见
做成人步态研究的人常有一个幻觉:正常参照很容易找。实际情况是,公开的、逐拍的、健康儿童步态节律数据极少。多数带「儿童」字样的步态库来自脑瘫、发育迟缓或术后随访,健康儿童作为对照只占少数,年龄分布也被病例构成牵着走;多数带「健康成人」字样的库又把年龄下限设在十八岁,中间那段从三岁到十三岁的空白没有人专门去填。
这个库填的正是这段空白。五十名儿童,月龄从四十到一百六十三,每人都是一段不加干预的自选步速行走,研究者只做了一件事:把每一次着地找出来,量出与前一次着地之间的时间。得到的东西既不是位置轨迹,也不是关节角度,而是最朴素的一列时长——同侧脚连续两次落地之间隔了多久,医学上叫步态周期,工程上叫步幅间隔。
朴素带来的好处是可迁移。任何一台能判定着地的设备,从鞋内压阻到 IMU 到压力跑台,最后都能导出同一列时长;因此这一份用某套实验室设备录下的序列,可以在其他设备、其他算法、其他年代的数据上对照。朴素带来的代价是信息窄:没有波形就没有步态相位,没有相位就推不出支撑相与摆动相,也推不出足底压力的空间分布。§7.3 会逐条列出由此损失的分析路径。
1.2 三条常见的错误期待
第一条错误期待,是把它当成儿科步态波形库。看到「250 Hz」很容易以为能拿到压力曲线;实际上这个数字只是 WFDB 头文件里给步幅序列声明的采样率,一字节恰好对应一拍,乘以 250 就是一秒,换算关系是为了让通用工具能读出坐标轴,不是为了给波形。真正的足底压力采样没有随库发布。
第二条错误期待,是把它当成病种对照库。库名里有 maturation(成熟),容易被读成「未成熟步态」,进而以为里面有发育异常儿童。参考论文的标题与摘要都写得很清楚:五十名孩子全部健康,研究问题是有没有继续发育,而不是谁不正常。库里不存在任何一个可以拿来做阳性对照的病人。
第三条错误期待,是把它当成纵向随访数据。五十名儿童每人只有一次访视,没有复测,没有随访。想研究「同一个孩子七岁时比五岁时稳多少」,这一份数据给不了;它给的是横断面——不同孩子在不同年龄各走一次,年龄效应只能靠受试者之间的比较来推。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 一条健康儿童的逐拍步幅序列 | 五十条,每条五百余拍 | 够 |
| 按年龄看节律稳定性的变化 | 月龄逐月记录,可自行分箱 | 够,但样本薄 |
| 儿科人群的步速参照 | 每人一个平均步速 | 够单人,不够分年龄 |
| 儿童的身高体重腿长 | 三项齐全,英寸与磅 | 够,需自行换算 |
| 原始足底压力波形 | 不发布 | 不够 |
| 支撑相、摆动相、双支撑 | 不发布 | 不够 |
| 步态成熟度的临床评分 | 不发布 | 不够 |
| 发育异常或疾病对照 | 没有 | 不够 |
| 同一名儿童的重复测量 | 没有 | 不够 |
| 高频或高精度时序 | 逐拍约一秒一个点 | 视任务而定 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 手上有一套儿童节律算法,缺一个干净的验证集 | 五十条无疾病混杂的健康序列,规模小到可以全量跑完 | 先读 §5.2 的批量脚本,把五十条一次拉下来 |
| 要做成人-儿童跨年龄的节律对照,缺儿童端 | 直接提供三至十三岁的儿童端,可与成人库拼接 | 注意成人库的时长与采样不同,需统一重采样后再比 |
| 要训练一个从步幅序列判定发育阶段的模型 | 可做小样本原型与特征筛选 | 五十例不足以训练,需找更大的合并来源 |
| 要在论文里引用一个公开的儿童步态节律基准 | DOI 与论文齐全,可直接引用 | 按 §9.3 的两条引用一并给出 |
| 想复现一项步态分形动力学的经典结论 | 论文、序列、人口学三者齐备 | 先按 §4.2 的案例把一条序列的波动看清楚 |
| 要做步态相位分析 | 无法支持 | 换到保留波形的库,或另配压力鞋垫自采 |
| 要研究发育迟缓与正常的分界 | 只能提供正常端 | 正常端用此库,异常端需另找临床队列 |
1.5 一句话判断
这是一个「只有正常、只有节律、只有五个人在一个年龄轴上」的小库;它的价值不在于大,而在于它把正常儿童的那一列时长干净地留了下来,任何想知道儿童步态「本该长什么样」的分析,都可以先在这里对一次表。
1.6 不适合谁:四条边界
第一,不适合需要波形的分析。没有足底压力曲线,就无法做任何基于波形形态的检测、分割或表征学习。第二,不适合任何需要阳性样本的任务。库里没有病人、没有异常、没有标注出问题的段落,做二分类时正类样本为零。
第三,不适合小年龄段的强推断。四十到一百六十三个月跨了十一年多,但五十人摊在十一年上,最薄的一档年龄只有一两个样本,任何按年龄细分后的统计都不稳定。第四,不适合纵向与干预研究。每人一次访视,没有任何前后对比的可能,也没有任何干预记录。
§2 数据构成与规格
2.1 三份派生物与一张表
整个库只有四个入口:data 目录、jap 目录、根目录的一包压缩档与一张校验和。data 目录里平铺着一百五十个文件,没有子目录,命名规则由「编号-月龄」构成。
| 文件族 | 数量 | 内容 | 是否必需 |
|---|---|---|---|
<编号>-<月龄>.txt |
50 | 两列制表符文本,时间与步幅时长 | 分析主入口 |
<编号>_<月龄>.hea |
50 | WFDB 头文件,单行 | 用 WFDB 工具链时必需 |
<编号>_<月龄>.str |
50 | 一字节一拍的步幅序列 | 用 WFDB 工具链时必需 |
table.csv |
1 | 五十行人口学与步速,有列名 | 分组与协变量时必需 |
SHA256SUMS.txt |
1 | 全部文件的校验和 | 校验完整性 |
gait-maturation-db.tar.gz |
1 | 旧版整包,一百二十余 KB | 可替代逐文件下载 |
jap/gait-reprint.pdf |
1 | 论文抽印本 | 读方法细节 |
jap/gait-reprint.ps |
1 | 同一篇论文的 PostScript 版 | 冗余,可忽略 |
三张 .png |
3 | 论文插图的花絮图 | 与数据无关 |
命名细节值得单说一段,因为它同时是索引和元数据。1-40.txt 表示受试者 1 号、四十个月大;同一名儿童的 WFDB 记录叫 1_40,连字符换成了下划线。这个换法不是随意的:WFDB 的文件名解析对连字符敏感,所以同一段数据在两种封装里用了两种分隔符。批量处理时若只按一种模式匹配,会漏掉一半文件。
2.2 字段与记录的完整字典
table.csv 八列,第一列自带取值范围注释,其余七列是纯值。
| 列序 | 列名 | 单位 | 含义 | 完整度 |
|---|---|---|---|---|
| 1 | subject-id(1-50) |
无 | 受试者编号 | 五十行全有 |
| 2 | age-months |
月 | 月龄,整数 | 五十行全有 |
| 3 | gender |
无 | M 或 F |
五十行全有,各 25 |
| 4 | height-inches |
英寸 | 身高,含半英寸 | 五十行全有 |
| 5 | weight-lbs |
磅 | 体重,整数 | 五十行全有 |
| 6 | leg-length-inches |
英寸 | 腿长,含半英寸 | 五十行全有 |
| 7 | Speed-m/sec |
米每秒 | 平均步速,五位小数 | 五十行全有 |
| 8 | Group |
无 | 年龄段标签 | 只填了四十三行 |
第八列的四个取值里,Young、Middle、Old 是年龄段标签,另有七行留空。列名里 Speed 首字母大写、m/sec 带斜杠,与其余全小写短横线风格不一致,这是 1999 年手写表头留下的痕迹,解析时不要按风格猜列名。
| 步幅文本的列 | 类型 | 单位 | 说明 |
|---|---|---|---|
| 第一列 | 浮点,四位小数 | 秒 | 本拍着地相对记录起点的时刻 |
| 第二列 | 浮点,四位小数 | 秒 | 本拍相对上一拍的时长 |
两列之间的关系可以直接验算:下一行的第一列减去本行第一列,约等于下一行的第二列。以受试者 1 的头两行为例,五点一五三三减去四点零四三三等于一点一一〇〇,与第二行第二列完全一致。这个自洽关系是这批数据最可靠的内部校验,§5.5 会把它写成一行代码。
2.3 一条记录的完整解剖
以受试者 1 号为例,也就是 §4.2 的案例所用的那条记录:四十个月,男性,身高四十点五英寸,体重四十三磅,腿长二十三英寸,平均步速每秒一点零四米。
subject-id,age-months,gender,height-inches,weight-lbs,leg-length-inches,Speed-m/sec,Group
1,40,M,40.5,43,23,1.04289,Young
步幅文本没有表头,开头与结尾各截几行,原文如下。
4.0433 0.8500
5.1533 1.1100
6.1000 0.9467
8.8533 2.7533
9.9633 1.1100
...
478.1133 0.8600
478.9533 0.8400
479.8633 0.9100
第四行那个二点七五秒很扎眼。一个四十个月的孩子平均一拍不到一秒,这里冒出一个接近三秒的间隔,说明中途有一次停顿或转身。这类长间隔在全库中并不罕见,它们不是噪声,而是连续行走中真实发生的事件;至于该剔除还是该保留,取决于分析目的,官方没有给出过滤规则。
WFDB 那一侧只有三行,头文件全文如下。
1_40 0 250 0
四个字段依次是记录名、通道数、采样率、注释长度。通道数为零,说明这不是一路连续采样的信号,而是一串稀疏事件;采样率 250 让第一列的时间进入 WFDB 的坐标体系,一个采样点对应四毫秒。1_40.str 是一串一字节整数,第一拍存 2035,约等于八点一四秒的累积,随后各拍在 1250 到 1300 之间小幅摆动,最后一拍是 0,作为结束标记。同一段数据在两套封装里描述的其实是同一组着地时刻,只是精度不同:文本保留四位小数,字节序列取整到毫秒。
2.4 年龄轴与三个标签
五十名儿童按年归档后的分布如下。这一列只统计结构,不做分布分析。
| 年龄段(整岁) | 人数 | 官方 Group 标签 |
|---|---|---|
| 3 岁 | 11 | Young |
| 4 岁 | 8 | Young |
| 5 岁 | 3 | 空 |
| 6 岁 | 7 | Middle |
| 7 岁 | 13 | Middle |
| 8 岁 | 1 | 空 |
| 10 岁 | 3 | 空 |
| 11 岁 | 7 | Old |
| 12 岁 | 3 | Old |
| 13 岁 | 2 | Old |
可以看到两处不均:七岁那一档人数最多,八岁与十岁之间有一段空档,九岁的孩子一个都没有。Group 标签的覆盖也停在不规则的位置上,五岁、八岁与十岁那几行没有填。
| 官方标签 | 覆盖的受试者编号 | 年龄边界 |
|---|---|---|
Young |
1 至 11 | 40 至 58 个月 |
Middle |
15 至 34 | 79 至 94 个月 |
Old |
39 至 50 | 133 至 163 个月 |
| 空 | 12 至 14、35 至 38 | 61 至 130 个月 |
标签的边界与人数都不均等,Middle 一档二十人,Young 一档十一人,Old 一档十二人,中间还空着七个人。这不是错误,而是一份手写整理的表在归档时的自然结果;把它当成分组变量直接做检验,就等于把七名儿童丢出样本,并强行让三组的年龄跨度不等。
2.5 与同类资源的字段差异
真正的差别不在列数,而在「有没有波形」和「有没有疾病标签」两处。
| 维度 | 本库 | gaitdb | gaitndd |
|---|---|---|---|
| 受试者 | 50 名健康儿童 | 15 人,含帕金森病 5 例 | 64 人,三病加对照 |
| 发布列 | 2 列 | 2 列 | 13 列 |
| 原始波形 | 无 | 无 | 双足两路 |
| 人口学表 | 8 列,含身高体重腿长 | 无独立表 | 8 列,含量表分 |
| 记录命名 | 编号-月龄 | 组别加年龄 | 组别加序号 |
| 每人时长 | 约八分钟 | 数分钟至十余分钟 | 五分钟 |
| 体积 | 1.4 MB | 数百 KB | 近二十 MB |
从表里能读出的结论只有一条:这一份与 gaitdb 同属「只发事件、不发波形」的瘦型,与 gaitndd 的厚型不同。瘦型的共同点是体积小、读取快、适合跑大批量方法;厚型的优势是能在原始信号上重做事件判定。§6.1 会把三者的分工摊开讲。
| 字段 | 本库 | gaitdb | gaitndd |
|---|---|---|---|
| 时间轴 | 有,秒,四位小数 | 有,秒 | 有,秒,相对记录起点 |
| 逐拍时长 | 有,秒 | 有,秒 | 有,秒 |
| 摆动相与支撑相 | 无 | 无 | 有,各两侧与占比 |
| 双支撑 | 无 | 无 | 有,秒与占比 |
| 身高体重 | 有,英寸与磅 | 无 | 有,米与千克 |
| 腿长 | 有 | 无 | 无 |
| 平均步速 | 有 | 无独立列,可自行估算 | 有 |
| 病种或量表 | 无 | 无 | 有三个量表分 |
| 年龄段标签 | 有,三档且有空缺 | 有,按组别 | 有,按组别 |
把三张字段表叠起来看,本库在「人口学」这一块反而比两个成人库更全:身高、体重、腿长三样都在,而 gaitdb 连独立的人口学表都没有。这与研究目的有关——要论证发育效应在按身高校正后依然存在,身高就必须进数据;而研究疾病与衰老时,身高只是可选的协变量。
2.6 体积与「够不够算」
整包不足两兆字节,一百五十个文本文件里绝大多数只有几 KB。这个体量的含义很直接:全量载入内存毫无压力,五十条序列拼成一张长表也不过数万行。反过来,这个体量也宣告了它不适合做什么——任何需要上百万步去学习的模型,在这里连一个批次都凑不出来。
| 量 | 官方口径 | 推算方式 |
|---|---|---|
| 受试者数 | 50 | 官方页面 |
| 记录数 | 50 | 目录文件计数 |
| 每条典型拍数 | 五百余 | 以受试者 1 号为例 |
| 全库约略总拍数 | 两万余 | 五十乘五百余 |
| 每拍时间分辨率 | 约一秒 | 步幅均值量级 |
| 单条序列典型跨度 | 约八分钟 | 首末时刻之差 |
「两万余拍」是一个量级估计,不是官方数字,写论文时不能直接引用;官方只给了受试者数与年龄跨度,其余都要自己从文件里算。
§3 它是一个发育问题,不是一台设备的记录
3.1 一个署名与四个名字
PhysioNet 页面上列了两名署名作者:Jeffrey Hausdorff,单位为波士顿的 Beth Israel Hospital;Chung-Kang Peng,单位为波士顿的 Harvard Medical School。引用论文署了四个人,另两位是 L. Zemany 与 Ary Goldberger。页面的两行署名没有写全论文作者,这是 PhysioNet 早期录入的惯例,署名栏只放维护或提交数据的人,而非全部作者。
| 角色 | 姓名 | 单位 |
|---|---|---|
| 页面署名作者 | Jeffrey Hausdorff | Beth Israel Hospital, Boston |
| 页面署名作者 | Chung-Kang Peng | Harvard Medical School |
| 论文合著者 | L. Zemany | 论文未在页面单列 |
| 论文合著者 | Ary Goldberger | 论文未在页面单列 |
| 发布平台 | PhysioNet | MIT Laboratory for Computational Physiology 维护 |
四人在同一时期还发表了另外几篇步态节律的论文,主题分别落在衰老、帕金森病与神经退行性疾病上。本库与这些论文共用一条采集与分析的技术路线,但它们是各自独立的资源,DOI 各不相同。
3.2 时间线:论文与数据几乎同时
| 时间 | 事件 |
|---|---|
| 1999 年 | 论文被 Journal of Applied Physiology 接收,刊于第 86 卷 |
| 1999 年 11 月 5 日 | 三张插图文件的时间戳 |
| 1999 年 12 月 16 日 | 整包压缩档的时间戳 |
| 1999 年 10 月 28 日 | 官方页面标注的发布日期与版本号 1.0.0 |
| 2019 年 2 月 20 日 | 校验和文件的时间戳 |
| 2026 年 | 仍为 1.0.0,无新版本 |
三个时间戳之间有轻微错位:页面写着十月二十八日发布,而压缩档的时间戳在十二月。这是 PhysioNet 早期从 PhysioBank 迁移到新平台时留下的痕迹,日期字段沿用了原始目录的创建时间,文件时间戳则是打包那一刻。两者相差不到两个月,对使用没有影响,但引用时应以页面标注的日期为准。
3.3 采集现场:只留下事件的痕迹
这一份数据最能说明问题的地方,是它把采集链条上「上游」的部分全部去掉了。曾经存在的传感器、模数转换、着地判定算法,一样都没有留下来;留下来的是判定之后的产物——一串时刻与一串时长。因此无法从数据本身判断着地判定用的是什么阈值、什么滤波器,也无法判断两名研究者对同一条记录是否会给出一致的切分。
这一点与 gaitndd 形成鲜明对照。那边的波形在,任何人都能重做一次着地判定,并把自己判出来的拍数与官方给出的逐拍表对照;这边的波形不在,判定这一步被锁死在 1999 年那次处理里,后面的人只能接受或质疑,不能重算。§7.4 的外部验证矩阵里,这一条是扣分最重的一项。
3.4 三层信息与它们的可信度
拆开看,这一份数据的信息分三层,可信度各不相同。
| 层级 | 内容 | 来源 | 可信度 |
|---|---|---|---|
| 第一层:事件 | 每次着地的时刻与相邻间隔 | 事件判定算法的输出 | 中,算法不可复查 |
| 第二层:人口学 | 年龄、性别、身高、体重、腿长 | 访视时测量与家长报告 | 高,直接测量 |
| 第三层:汇总 | 平均步速、年龄组标签 | 研究者整理 | 中,标签有缺口 |
第一层决定了能做节律分析,但这一层恰好是最不可复查的;第二层最可靠,却是任何一份临床数据都会有的;第三层最方便,也最容易被误用。使用时的常识是:把第一层当测量值、第二层当协变量、第三层当参考,而不要反过来把第三层当成金标准。
3.5 四条同门线索为何能各自立住
同一批人做过四个主题——发育、衰老、帕金森病、神经退行性疾病——却没有把它们合成一个大库。这件事在今天看来有点反常:现代平台化做法通常倾向于合并,一个入口、一张统一表、一个标签字段,用起来更省事。
不合并是有道理的。四个主题的受试者招募渠道不同:儿童来自小学与幼儿园,老人来自社区,病人来自门诊。行走方案也不同:儿童走八分钟,病人走五分钟,健康成人有时绕圈十几分钟。若强行并入一个库,就得先统一时长与流程,而统一会削弱每个主题各自的对照强度。分开发布,每个库只服务一个问题,反而更干净。
代价是使用者的负担。想研究「三岁到八十岁」的节律曲线,必须自己跨三个库拼接,还要处理单位、时长与采集条件的差异。这是把整合成本从发布者转移给了使用者,是早期数据共享的典型形态。
| 主题 | 对应资源 | 受试者 | 时长方案 |
|---|---|---|---|
| 发育 | 本库 | 50 名健康儿童 | 约八分钟连续行走 |
| 衰老 | gaitdb 的青年与老年组 | 10 人 | 数分钟至十余分钟 |
| 帕金森病 | gaitdb 与 gaitndd 的帕金森组 | 共 20 例 | 五分钟至十余分钟 |
| 其他神经退行性病 | gaitndd 的亨廷顿与渐冻症组 | 33 例 | 五分钟 |
上表的人数不能相加成「一个更大的库」,因为其中可能有同一批受试者在不同研究里重复出现,官方没有提供去重依据。这张表只用来回答「哪个主题该去哪个库找」。
§4 它最独特的东西:一列时长里的发育信号
4.1 只剩一列,为什么仍然有用
如果只能留一列物理量来描述行走,大多数人会选速度,或者步频。这一份数据留的是步幅时长,也就是步态周期。选它的理由写在论文的逻辑里:速度与步频都是平均值,平均值稳定并不代表每一步都稳定;而发育期的核心变化,恰恰发生在这种逐拍之间的波动上。
于是这列时长承担了两类信息。第一类是它自己的均值,反映孩子走得多快、节奏多慢;第二类是它的波动结构,反映每一步与下一步之间如何相关。前者一眼能看懂,后者需要专门的工具,论文用的是去趋势波动分析这类方法。两类的区别可以这么记:均值告诉你「平均走多快」,波动结构告诉你「节奏稳不稳、稳得有没有章法」。
4.2 案例:受试者 1 号那五百三十三拍
以 §2.3 已经解剖过的受试者 1 号为例。这孩子四十个月,是库里最小的几个之一。整条序列从第四秒出头开始,到第四百八十秒结束,共五百三十三拍,平均每拍零点八九秒左右。
把它按时间顺序画出来,会看到三个层次的起伏。最短的一层是逐拍的快慢交替,相邻两拍差个几十毫秒,这是任何行走都有的抖动。中间一层是几十拍到上百拍的漂移,节奏时快时慢,走二三分钟换一次。最长的一层是整段记录里那一次长达二点七五秒的中断,它把序列从中间打断了一次。
三个层次对分析的意义不同。第一层是噪声与生理抖动的混合,多数方法会把它当高频成分滤掉;第二层是长程相关的主要来源,也是论文关注的发育对象;第三层是事件,处理不当会污染前两层的估计。同一条序列在三类工具下会给出三组不同的结论,这并不是数据的问题,而是「要不要剔除长间隔」这个前置选择的结果。
在 §5.3 与 §5.5 里,这条序列会被重新读入,用来演示两种封装的一致性;在 §7.3 里,它会被用来解释长间隔为何是这批数据最需要提前声明处理规则的地方。
4.3 为什么「发育」要靠随时间的变化来看
如果只看平均步幅,四十个月的孩子与十岁的孩子差别其实不大,都在一秒上下,最快最慢也就差三四成。真正拉开的差距在波动的组织方式上:论文的摘要里写得很直白,三岁与四岁的孩子,逐拍之间的变异显著大于六岁与七岁;六岁与七岁又显著大于十一到十四岁;而且这个年龄效应在按身高校正之后依然存在。
「按身高校正之后依然存在」这句话是本库最值得记住的一条。它意味着发育带来的变化不只是腿变长了、步幅自然就长了,而是控制本身在变得更精细。这正好解释了为什么一个只有时长、没有关节角度、没有肌电的小库,仍然能支撑一篇发育学的论文:它选的量恰好落在控制能体现出来的那一层。
4.4 这份数据真正被用来回答的问题
把它能回答的问题排一下,大致是三类。第一类是同年龄段的节律特征描述,回答「这个年龄的孩子走起来波动多大」。第二类是跨年龄段的趋势,回答「从三岁到十三岁,波动怎么收窄、相关怎么变化」。第三类是与其他人群的对照,回答「儿童与成人、与病人的节律差在哪里」。
三类之外还有一类常被误以为能做:判断某个具体孩子发育是否正常。这一份做不了。它给出的是群体层面的趋势与参照,没有任何一条记录带诊断,也没有任何一条记录来自确诊儿童,因此不存在一个可以把个体挂上去的正常范围。
三类问题的答案,对分析方法各有要求。第一类只需要描述统计,把每条序列的波动量算出来即可,但要先说清长间隔怎么处理,否则同一批孩子的数字会随规则变化。第二类需要把个体值聚成年龄趋势,常用的做法是把月龄当连续变量做回归,而不是按整岁切段——切段会把七岁那一档的十三个样本与相邻几年割开,损失分辨率。第三类跨库比较最难,因为两个库的行走时长不同、设备不同、着地判定不同,任何差异都可能来自测量而非生理。
| 想回答的问题 | 需要什么量 | 本库够不够 |
|---|---|---|
| 这个年龄的孩子波动多大 | 每条序列的变异量 | 够 |
| 波动随年龄怎么变 | 变异量与月龄的回归 | 够,样本薄 |
| 与成人比差多少 | 两个库的同一定义量 | 勉强,测量条件不同 |
| 与病人比差多少 | 需病人组的同一定义量 | 另找病种库 |
| 某个孩子是否正常 | 个体参考区间 | 不够,无区间 |
4.5 边界条件:什么情况下它不再适用
第一种情形是需要相位信息时。只要任务涉及支撑相、摆动相、双支撑、足底压力中心,这一份就完全失效,因为它从没记录过这些。
第二种情形是比较采集设备时。数据的采集设备、采样细节都没有公布,无法用来评价某台新设备与旧设备的差异。第三种情形是跨库拼接时不做归一。别的库多以分钟计时长、以毫秒计步幅,直接混在一起会产生单位级别的错误。
第四种情形,是把「健康」当成无条件的健康。五十名儿童的健康是研究者按当时标准筛的,筛选标准没有写进数据说明;用于今天的研究时,不能假定这一批孩子按现行标准仍然全部健康。
§5 怎么拿到:从一张表到一条能跑的序列
5.1 目录结构与下载面
官方给出三条取数路径,任选其一。
#-- 路径一:整包下载(含旧版压缩档)
wget https://physionet.org/files/gait-maturation-db/1.0.0/gait-maturation-db.tar.gz
#-- 路径二:镜像整个 1.0.0 目录,保留 data 与 jap 两个子目录
wget -r -N -c -np https://physionet.org/files/gait-maturation-db/1.0.0/
#-- 路径三:用 AWS 命令行工具匿名同步,不占带宽配额
aws s3 sync --no-sign-request s3://physionet-open/gait-maturation-db/1.0.0/ ./gmd
#-- 校验:目录内附 SHA256SUMS.txt,逐文件比对
cd gmd && sha256sum -c SHA256SUMS.txt | tail -5
三条路径拿到的是同一批文件。路径一的压缩档只有一百二十余 KB,体积小于页面标注的未压缩总量,说明里面是压缩后的原始文件而非全部派生物;因此要做完整分析,建议用路径二或路径三,直接取 data 目录。
5.2 批量抓取与索引
不装任何东西,用标准库就够了。下面的脚本把五十条序列与人口学表一次拉到本地,并按文件名解析出编号与月龄。
import csv, io, pathlib, urllib.request
BASE = "https://physionet.org/files/gait-maturation-db/1.0.0/data/"
OUT = pathlib.Path("gmd"); OUT.mkdir(exist_ok=True)
def get(name):
with urllib.request.urlopen(BASE + name) as r:
return r.read()
table = list(csv.DictReader(io.StringIO(get("table.csv").decode())))
for row in table:
#-- 文件名把编号与月龄同时写进名字,用连字符分隔
name = f"{row['subject-id(1-50)']}-{row['age-months']}.txt"
(OUT / name).write_bytes(get(name))
print("downloaded", len(table), "stride files")
脚本只做两件事:先读表,再按表里的编号与月龄拼出文件名。之所以要拼而不是直接遍历目录,是因为目录列表页是 HTML,解析它反而更脆;table.csv 的五十行正好覆盖五十个文件,用它做索引最稳。
5.3 读成一张表
两列文本没有表头,读的时候顺手补上列名,并把 table.csv 的关键列并进来。
import csv, pathlib
import pandas as pd
OUT = pathlib.Path("gmd")
meta = pd.read_csv(OUT / "table.csv")
meta = meta.rename(columns={"subject-id(1-50)": "sid",
"Speed-m/sec": "speed"})
rows = []
for _, m in meta.iterrows():
f = OUT / f"{m.sid}-{int(m['age-months'])}.txt"
df = pd.read_csv(f, sep=r"\s+", header=None, names=["t", "stride"])
df["sid"] = m.sid
df["age"] = m["age-months"]
rows.append(df)
long = pd.concat(rows, ignore_index=True)
print(long.groupby("sid").size().describe()[["min", "50%", "max"]])
跑完之后会得到一张长表:每行一次着地,带受试者编号与月龄。groupby("sid").size() 给出每人的拍数,最小值与最大值之间差距不小,这与各段行走的实际时长有关,而不是数据缺失。
5.4 用 WFDB 读第二份封装
装了 wfdb 包之后,同一段数据可以从前门读进来。头文件里声明的采样率会被自动套上坐标轴。
import wfdb, numpy as np
rec = wfdb.rdrecord("gmd/1_40")
sig = rec.p_signal[:, 0]
fs = rec.fs #-- 头文件声明 250,即一个采样点四毫秒
t = np.arange(len(sig)) / fs
#-- 与文本版本对照:取前五拍,看两套封装是否落在同一秒上
txt = np.loadtxt("gmd/1-40.txt")
print(np.round(t[:5], 2), np.round(txt[:5, 0], 2))
两套封装给出的前几拍时刻相差在毫秒量级,差异来自字节序列的整数取整。做节律分析时这个量级可以忽略;做精确的时序对齐时,应统一使用文本版本。
5.5 三条最短的自检
拿到数据的第一件事不是建模,而是确认三件事:两列自洽、两套封装一致、人口学表能对上。
import numpy as np, pandas as pd
df = pd.read_csv("gmd/1-40.txt", sep=r"\s+", header=None, names=["t", "s"])
#-- 自检一:下一拍时刻减本拍时刻,应等于下一拍的时长
err = np.abs((df["t"].shift(-1) - df["t"])[:-1] - df["s"].values[1:])
print("max gap error (s):", round(float(err.max()), 4))
#-- 自检二:步幅列不应有非正值,零值只在末行出现
print("nonpositive strides:", int((df["s"] <= 0).sum()))
#-- 自检三:人口学表五十行,编号应连续
meta = pd.read_csv("gmd/table.csv")
print(meta["subject-id(1-50)"].is_monotonic_increasing, len(meta))
三项全过,说明文件没被截断、没被改写。若第一项的最大误差超过零点零一秒,多半是下载中断或文件被换行符处理过。
5.6 三类常见读取错误
第一类是把连字符与下划线混了。1-40.txt 与 1_40.hea 是同一名儿童,但分隔符不同;用 *.txt 匹配再拼 .hea 名字,一定找不到文件。第二类是把采样率当成物理采样。250 Hz 只是坐标轴刻度,真正的物理量是每秒一拍上下;按 250 点做滑窗,窗口里永远只有一个点。
第三类是把 Group 列当完整字段读。七行空缺,read_csv 默认会把它读成 NaN,之后做 groupby 会静默丢掉七名儿童;要保留样本,应先把空值填成 Unknown 再分组。
§6 与库内条目的关系
6.1 关系图谱
站内步态一族已有两条词条,本篇是第三条。三者不是同一个库的版本迭代,而是同一课题组在同一平台上架的三个独立资源,各自有独立的 DOI、独立的受试者、独立的记录命名与独立的发布日期。
| 维度 | gaitdb | gaitndd | 本库 |
|---|---|---|---|
| 全名 | Gait in Aging and Disease Database | Gait in Neurodegenerative Disease Database | Gait Maturation Database |
| DOI | 10.13026/C2C889 | 10.13026/C27G6C | 10.13026/C2H014 |
| 上线 | 2000 年 10 月 13 日 | 2000 年 12 月 21 日 | 1999 年 10 月 28 日 |
| 受试者 | 15 人 | 64 人 | 50 人 |
| 人群 | 青年、老年、帕金森病 | 帕金森病、亨廷顿病、渐冻症、对照 | 健康儿童 |
| 发布列 | 2 列 | 13 列 | 2 列 |
| 原始波形 | 无 | 双足两路 | 无 |
| 每人时长 | 数分钟至十余分钟 | 五分钟整 | 约八分钟 |
| 记录命名 | 组别加年龄 | 组别加序号 | 编号-月龄 |
三者的分工可以按「年龄轴」排:本库占的是三到十三岁这一段,全部健康;gaitdb 占的是两端——二十来岁的青年与七十多岁的老年,中间夹五个帕金森病患者;gaitndd 不占年龄轴,占的是病种维度,把三种神经退行性疾病放在同一个五分钟方案下。三条拼起来,恰好覆盖「发育、衰老、退变」三件事,缺的正是中间最普通的成年健康段。
| 你要做的事 | 该用哪个 | 缺口在哪 |
|---|---|---|
| 儿童节律的正常参照 | 本库 | 无疾病端 |
| 老年与青年的节律对照 | gaitdb | 无儿童端 |
| 三种神经退行性疾病的节律比较 | gaitndd | 无儿童端、无青年端 |
| 跨年龄的节律趋势(儿童到老年) | 本库 + gaitdb | 中间缺成年健康段,两端采集条件不同 |
| 需要从波形重做着地判定 | gaitndd | 另两个都不含波形 |
| 只需要一列时长做方法验证 | 三者任一 | 本库与 gaitdb 更轻 |
能不能合并使用,要分三层答。第一层,分析对象可以合并:三者最终都能导出一列步幅时长,只吃这一列的方法在三条上都能跑。第二层,测量条件不能等同:本库的行走时长、采集设备、着地判定都与另两条不同,把它们拼成一条长序列时,边界处的跳变是测量差异,不是生理差异。第三层,受试者不能假定重叠:三份页面的 DOI、文件名体系、人群年龄都不交叉,官方也没有提供任何受试者对应表,因此不能把本库的儿童与 gaitdb 的青年当作同一批人,也不能假定存在谁是谁的子集。
6.2 检索路径
站内凡带步态的页,标签都落在 生理信号 之下的 步态与运动 上,本库另外挂了 儿科。因此从 步态与运动 标签页出发,能一次看到三者;从 儿科 标签页出发,本库是当前唯一一条。
| 入口 | 能到达 | 说明 |
|---|---|---|
标签 步态与运动 |
本库、gaitdb、gaitndd 及相关词条 | 最全的入口 |
标签 儿科 |
本库 | 站内儿科标签下的步态页 |
关键词 stride interval |
三条全部命中 | 三条都发布了逐拍时长 |
关键词 maturation |
仅本库 | 另两条不涉及发育 |
DOI 前缀 10.13026/C2 |
gaitdb 与本库 | PhysioNet 早期 DOI 编号段相邻 |
值得注意的是,本库与 gaitdb 的 DOI 都以 10.13026/C2 开头且尾段接近,这说明两者在 PhysioNet 的编号体系里几乎是同时入库的,与 §3.2 的时间线一致。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
对这个小库最常见的误判,是拿「体量」与「字段数」当质量分。体量小、字段少,在这类数据上并不构成缺陷:它的设计目标就是一列时长加一张人口学表,任何超出这个范围的期待都是错位。真正的质量分应该落在两件事上——它有没有干净地给出它承诺的东西,以及它有没有把不该省的东西也省了。
按这个标准,它在前一件上做得很好:五十条序列完整、两列自洽、人口学表齐全、论文随库发布。在后一件上有一处硬伤:原始足底波形没有发布,导致着地判定这一步不可复查。§7.3 会把这一处的后果逐条列出来。
7.1 DAIMS 五维评分
DAIMS 是数据可用性与互操作性的一套评估框架,本节按它的五个维度给分,满分一百。
| 维度 | 得分 | 依据 |
|---|---|---|
| 数据文档 | 16 / 20 | 页面说明详尽,论文随附,但采集设备与判定规则未写 |
| 数据质量 | 17 / 20 | 两列自洽、编号与月龄一致,Group 列有缺口 |
| 数据访问 | 19 / 20 | 免注册、三条下载路径、有校验和 |
| 数据互操作 | 12 / 20 | 提供 WFDB 封装是加分,但无列名、无单位声明、无元数据标准 |
| 数据复用 | 11 / 20 | 只有健康儿童、只有一列时长,复用面窄 |
合计七十五分。扣分集中后两项:互操作卡在「有格式无字典」——WFDB 侧有头文件,文本侧却没有一行说明两列是什么;复用卡在「能做的事太少」——没有波形、没有病种、没有纵向,能承载的分析类型是有限的一小撮。
7.2 三处需要自己核对的地方
第一,年龄口径。官方页面写四十到一百六十三个月,论文摘要写三到十四岁,两者不矛盾但不能互换使用;按论文口径做年龄分箱,会与 age-months 列的分箱边界对不上。
第二,行走时长。官方页面没有给每段多长,只能从每条记录的首末时刻自己算;受试者 1 号是八分钟左右,其他记录未必相同,做跨受试者比较时应先算一遍。
第三,Group 列的边界。标签只填了四十三行,且三组的年龄跨度不等;官方没有解释为何这样填,也没有给出填补规则。
7.3 已知的、可枚举的偏差
第一,人群偏差:全部健康、全部来自同一家医院的招募范围、没有种族与社会经济地位信息,跨人群外推时没有校正依据。第二,年龄偏差:五十人摊在十一年上,部分年龄只有一两个样本,最薄处几乎无法做年龄内估计。
第三,技术偏差:着地判定算法未公开,无法评估误判率;长间隔(如 §4.2 案例里那一次二点七五秒)的存在说明原始序列里混着停顿与转身,官方未给过滤规则。第四,时间偏差:数据采集于 1999 年之前,儿童的营养与活动模式与今天不同,用作当代参照时应说明年代差。
7.4 外部验证矩阵
| 可验证的项 | 能否在库内验证 | 替代办法 |
|---|---|---|
| 两列自洽 | 能,逐行可算 | 无需外部 |
| 两套封装一致 | 能,逐拍对照 | 无需外部 |
| 着地判定是否正确 | 不能,无波形 | 需原始压力信号,或按论文描述的算法自行复采 |
| 年龄与身高是否真实 | 不能,无原始记录 | 只能采信表内数值 |
| 步速是否与步幅一致 | 部分能,可做量级核对 | 需自行按步长乘步频估算 |
| 发育趋势是否可复现 | 能,按论文方法重跑 | 需自行实现分析流程 |
| 验证层级 | 覆盖情况 | 说明 |
|---|---|---|
| 库内自洽 | 完整 | 两列关系与两套封装都能自证 |
| 与论文一致 | 高 | 论文给出方法,序列在库,可重跑 |
| 与原始信号一致 | 无 | 原始信号未发布 |
| 与其他设备一致 | 无 | 无同人异机的配对记录 |
7.5 它为何能持续:一个没人会重复去做的测量
这类数据能长期存在,靠的不是被频繁引用,而是没有再生产的动力。要在今天重新做一次「五十名三到十三岁健康儿童、每人八分钟连续行走、逐拍标注」的采集,成本远高于下载这一份,而结论的增量却有限——发育趋势这种大尺度的生理事实,不会因为换了一批孩子就翻盘。
于是它变成了一个稳定参照物:体积小到可以随论文附带,年代早到成为「经典」,授权开放到没有任何门槛,任何做儿科节律的人都愿意先在上面跑一遍。这种位置不需要维护,只需要不被下架,而 PhysioNet 的长期托管恰好提供了这一点。
§8 生态位与历史
8.1 历史沿革
PhysioNet 的前身 PhysioBank 在上世纪九十年代末开始接收研究者提交的数据集,本库是那一批里较早的一个。文件名里带「月龄」、目录里放论文抽印本(jap 取自期刊名缩写),都是那个年代的惯例:数据不是独立产品,而是论文的附件。
从 1999 年到今天,版本号一直是 1.0.0。页面在 2012 年有过一次索引文件的修订,2019 年补了校验和,之外没有内容变动。这种长期静止在数据资源里并不常见,它同时说明两件事:内容已经足够稳定,也没有人打算扩充它。
8.2 与同期资源的分工
同一时期上架的若干步态库,选择的技术路线可以按「留什么」分成两派。一派留波形,体积大、可复查、适合做信号处理;另一派留事件,体积小、不可复查、适合做统计与节律分析。本库与 gaitdb 属于后一派,gaitndd 属于前一派。
| 时期 | 代表资源 | 留下的东西 | 适合的分析 |
|---|---|---|---|
| 1999 | 本库 | 逐拍时长与人口学 | 节律统计、发育趋势 |
| 2000 | gaitdb | 逐拍时长 | 长程相关、衰老对照 |
| 2000 | gaitndd | 双足波形与十三列相位 | 信号处理、相位分析 |
| 之后 | 各类可穿戴步态库 | 多轴 IMU 原始序列 | 深度表征、活动识别 |
四代之间的差别不只是传感器,还有「留给下一个人多少余地」。留波形的一代把判定权交给了使用者,留事件的一代把判定权收归了采集者;这不是质量高低,而是两种不同的取舍。
8.3 生态位:年龄轴上的一段
在「发育、衰老、退变」这个三分法里,本库唯一占住的是发育段。这个位置的稀缺性来自采集难度:儿童配合度低、伦理审查严、单次能走的时长有限,导致健康儿童的长程节律数据天然稀少。一旦有一份公开出来,它就会长期被人引用,哪怕体量很小。
| 生态位 | 谁来填 | 本库是否覆盖 |
|---|---|---|
| 儿童健康节律 | 本库 | 是 |
| 青年健康节律 | gaitdb | 否 |
| 老年健康节律 | gaitdb | 否 |
| 神经退行性疾病 | gaitndd | 否 |
| 发育异常与康复 | 各类临床儿科库 | 否 |
8.4 谁在用它,用来做什么
按库的性质推断,使用者大致集中在三类:做非线性时间序列方法的人,拿它当方法验证集;做儿科运动发育的人,拿它当正常参照;做教学的人,拿它当「逐拍时长」这个概念的最小样本。三类用法对数据的要求都不高,这也解释了为什么一个只有两列的文件能活二十多年。
需要说明的是,本节的三类使用者是从数据的形态与论文主题推断的,官方页面没有给出使用统计,也没有引用计数。若需要确切的引用规模,应自行到文献数据库检索。
§9 使用指引
9.1 三种角色的路径
| 角色 | 建议起点 | 建议跳过 |
|---|---|---|
| 方法研究者 | §5.3 读表,全量载入后直接跑算法 | §3 的采集史可略读 |
| 儿科或康复研究者 | §2.4 年龄轴,§4.3 发育逻辑 | §5.4 的 WFDB 读取 |
| 教学使用者 | §2.3 的单条解剖,§4.2 的案例 | §7 的评分细节 |
三类角色有一个共同的第一动作:先把 table.csv 读进来,弄清楚五十行的年龄与标签分布,再去决定要不要按年龄分箱。跳过这一步直接建模,多半会在分组上踩坑。
9.2 一条最短的可用流程
从下载到出一张年龄趋势图,最省事的一条路如下。
import io, pathlib, urllib.request
import numpy as np, pandas as pd
BASE = "https://physionet.org/files/gait-maturation-db/1.0.0/data/"
OUT = pathlib.Path("gmd"); OUT.mkdir(exist_ok=True)
def fetch(name):
with urllib.request.urlopen(BASE + name) as r:
data = r.read()
(OUT / name).write_bytes(data)
return data
meta = pd.read_csv(io.BytesIO(fetch("table.csv")))
stats = []
for _, m in meta.iterrows():
sid, age = int(m["subject-id(1-50)"]), int(m["age-months"])
raw = fetch(f"{sid}-{age}.txt").decode()
df = pd.read_csv(io.StringIO(raw), sep=r"\s+", header=None,
names=["t", "stride"])
#-- 长间隔视为事件,先剔除再算波动,规则需在论文里写明
s = df["stride"]
s = s[(s > 0) & (s < 2.0)]
stats.append({"sid": sid, "age": age,
"n": len(s), "cv": s.std() / s.mean()})
out = pd.DataFrame(stats).sort_values("age")
print(out.head())
这段代码有三处需要注意。s < 2.0 这个阈值是人为设定的,库里没有官方过滤规则,任何阈值都要在方法部分交代。cv 用的是变异系数,比标准差更适合跨年龄比较。fetch 每次联网,跑全量会发五十余次请求,若被限速应改为一次拉整包。
9.3 引用方式
官方要求两条引用同时给出:一条是原始论文,一条是 PhysioNet 平台本身。
| 引用对象 | 内容 |
|---|---|
| 数据 | Gait Maturation Database, version 1.0.0, PhysioNet, DOI 10.13026/C2H014 |
| 论文 | Hausdorff JM, Zemany L, Peng C-K, Goldberger AL. Maturation of gait dynamics: stride-to-stride variability and its temporal organization in children. J Appl Physiol. 1999; 86: 1040-1047 |
| 平台 | 官方推荐按 PhysioNet 页面给出的平台引用格式,随年份更新 |
APA 格式下,数据条应写成「作者(年份)。标题(版本 1.0.0)[数据集]。PhysioNet。DOI」,论文条按期刊常规格式。
§10 AI 使用声明
| 项目 | 说明 |
|---|---|
| 用途 | 本页用于介绍数据集的结构、边界与取数方式 |
| 数据来源 | 官方 PhysioNet 页面、data 目录内的文件与论文摘要 |
| 数字口径 | 规模、结构、边界三类,官方说多少就写多少 |
| 未核实项 | 每段行走的确切时长、着地判定算法、受试者筛选标准 |
| 未做之事 | 未重新跑论文的分析、未评估着地判定的准确率 |
| 推断标记 | §8.4 的使用者类型为推断,非官方统计 |
| 更新约定 | 版本变化或页面口径变化时同步修订 |
| 责任边界 | 用于临床决策前须自行验证,本页不构成医学建议 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 这是一个儿科疾病步态库 | 五十名儿童全部健康,无疾病标签 | 官方数据说明段 |
| 250 Hz 意味着有原始压力波形 | 250 只是 WFDB 头文件给步幅序列声明的采样率 | 1_40.hea 单行文本 |
| 年龄是 3 到 14 岁 | 页面写 40 至 163 个月,约 3 岁 4 个月到 13 岁 7 个月 | 官方页面与 age-months 列 |
| Group 列可以直接分三组 | 只填了四十三行,三组人数与年龄跨度都不等 | table.csv 第八列 |
| 每人走了统一时长 | 官方未公布时长,各条记录首末时刻不同 | 仅能从文件自行计算 |
文件名 1-40 里的 40 是编号 |
40 是月龄,编号是 1 | 官方页面命名说明 |
| 与 gaitdb 是同一批受试者 | DOI、人群、命名全不同,无对应表 | §6.1 对照表 |
| 数据可以训练深度模型 | 全库约两万余拍,容量不足以从零训练 | §2.6 量级估计 |
| 有随访,可做纵向分析 | 每人一次访视,无重复测量 | 官方数据说明段 |
FAQ
问:这个库和站内已有的 gaitdb、gaitndd 是同一个课题组的吗?
是同一个课题组,但三者是三个独立资源,不是同一个库的分支。它们共用一条技术路线,DOI 与发布内容各自独立。
问:五十个孩子是怎么走的?
在一次实验室访视中连续行走,自选步速,每人约八分钟。官方没有给出更细的行走路线描述。
问:为什么有两列一样的封装?
一列文本给人看、给表格工具读,一套 WFDB 给信号处理工具链读。两者描述同一组着地时刻,精度略有不同。
问:一条记录五百多拍够用吗?
做单人的节律分析够,做模型的训练集不够。全库两万余拍,只够做方法验证或小样本原型。
问:可以根据年龄补全 Group 列吗?
可以,但要在论文里声明是按 age-months 自行划分,而不是沿用官方标签;两种做法的样本量不同。
问:长间隔应该删掉吗?
取决于任务。做平均步幅可以保留,做波动结构必须声明处理规则,因为一次停顿会显著抬高变异的估计。
问:能拿到足底压力波形吗?
不能,本库从未发布波形。需要波形请换到 gaitndd 一类保留原始信号的库。
问:九岁的孩子为什么一个都没有?
官方没有解释。样本是按当时能招募到的儿童整理的,不是按年龄配额抽样。
问:这个库现在还有人维护吗?
官方页面仍在,版本仍是 1.0.0,没有内容更新;平台层面的维护由 PhysioNet 承担。
问:引用时只引论文可以吗?
不建议。官方明确要求同时给出数据条与论文条,只引论文会让后来者找不到版本号与 DOI。
问:能不能用它判断某个孩子走路是否正常?
不能。它给的是群体趋势,没有个体诊断标准,也没有临床判定规则。
术语表
| 术语 | 含义 |
|---|---|
| 步态周期 | 同一只脚连续两次着地之间的完整过程 |
| 步幅间隔 | 步态周期的时间长度,本库的第二列 |
| 步幅间变异 | 相邻拍之间时长的波动程度,常用标准差或变异系数表示 |
| 长程相关 | 相隔很多拍的时长之间仍有关联的性质 |
| 去趋势波动分析 | 一种估计长程相关的方法,论文所用工具 |
| 着地事件 | 足部接触地面的瞬间,逐拍序列的切分依据 |
| WFDB | 面向生理信号的开放数据格式与工具链 |
| 头文件 | 声明通道、采样率与文件名的文本文件 |
| 采样率 | 每秒钟的采样点数,本库为坐标轴刻度 |
| 帧 | WFDB 中一个采样点,本库为四毫秒 |
| 逐拍表 | 每次着地一行、两列的派生文本 |
| 人口学表 | 五十行的年龄性别身高体重腿长与步速表 |
| 月龄 | 以月为单位的年龄,本库用它编码文件名 |
| 年龄段标签 | Group 列的三个取值与一处空缺 |
| 自选步速 | 受试者按自己习惯的速度行走 |
| 连续行走 | 中途不停、不间断的一段路 |
| 抽印本 | 论文的独立重印件,本库放在 jap 目录 |
| ODC 署名 | 一种要求署名的开放数据授权 |
| DOI | 数字对象标识符,用于稳定引用 |
| 版本号 | 本库长期停留在 1.0.0 |
| 外部验证 | 用本库之外的数据检验结论 |
| 内部自洽 | 同一份文件内的两列互为校验 |
| 数据字典 | 说明每列含义与单位的文档,本库缺 |
| 偏差 | 样本或方法带来的系统性偏离 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 全名 | Gait Maturation Database | 官方页面 | 官方 |
| 版本 | 1.0.0 | 官方页面 | 官方 |
| 发布日期 | 1999 年 10 月 28 日 | 官方页面 | 官方 |
| DOI | 10.13026/C2H014 | 官方页面 | 官方 |
| 受试者数 | 50 | 官方页面 | 官方 |
| 年龄下限 | 40 个月 | 官方页面 | 官方 |
| 年龄上限 | 163 个月 | 官方页面 | 官方 |
| 男女 | 各 25 名 | 论文摘要 | 论文 |
| 未压缩体积 | 1.4 MB | 官方页面 | 官方 |
| 采样率声明 | 250 Hz | 头文件 | 文件 |
| 人口学表行数 | 五十行 | 文件 | 文件 |
| 每组文件数 | 各 50 个 | 目录 | 文件 |
| 受试者 1 号拍数 | 533 | 文件 | 文件 |
| 受试者 1 号末拍时刻 | 479.86 秒 | 文件 | 文件 |
| 许可 | ODC-BY 1.0 | 官方页面 | 官方 |
附录 B:数字的来源分层
| 层级 | 定义 | 本页涉及的项 |
|---|---|---|
| 官方页面 | PhysioNet 页面与其中列出的说明 | 受试者数、年龄跨度、版本、日期、许可、体积 |
| 论文摘要 | Journal of Applied Physiology 论文摘要 | 25 名女孩、3 至 14 岁、年龄效应结论 |
| 文件 | 从 data 目录直接读取 |
拍数、首末时刻、表行数、Group 覆盖 |
| 未核实 | 页面与文件均未给出 | 每段确切时长、着地判定规则、招募标准 |
附录 C:完整参考文献
| 编号 | 文献 |
|---|---|
| 1 | Hausdorff JM, Zemany L, Peng C-K, Goldberger AL. Maturation of gait dynamics: stride-to-stride variability and its temporal organization in children. Journal of Applied Physiology. 1999; 86(3): 1040-1047. DOI 10.1152/jappl.1999.86.3.1040. PMID 10066721. |
| 2 | Gait Maturation Database, version 1.0.0. PhysioNet. DOI 10.13026/C2H014. |
| 3 | PhysioNet 平台引用,按官方页面给出的格式,年份随更新变化。 |
附录 D:任务代码
把三条同门库放在一起看的代码骨架,只保留接口,逻辑按需补。
import wfdb
from wfdb import processing
def load_stride_txt(path):
#-- 两列文本:时间与步幅,用于本库与 gaitdb 一类瘦型资源
import pandas as pd
return pd.read_csv(path, sep=r"\s+", header=None, names=["t", "stride"])
def load_stride_wfdb(rec_path, chan=0):
#-- WFDB 记录:用于 gaitndd 一类含波形的资源
rec = wfdb.rdrecord(rec_path)
sig = rec.p_signal[:, chan]
peaks = processing.xqrs_detect(sig, fs=rec.fs)
return peaks / rec.fs, rec.fs
def normalize_stride(series):
#-- 统一到秒与正拍,跨库拼接前必须先过这一步
s = series[series > 0]
return s / 1000.0 if s.median() > 10 else s
normalize_stride 里的判据是一个实用技巧:步幅时长以秒计时,中位数在一秒上下;以毫秒计时,中位数在一千上下。用中位数的量级区分单位,比按列名猜更可靠。
附录 E:如果只记五件事
| 序 | 要点 |
|---|---|
| 1 | 五十名健康儿童,三岁到十三岁,男女各半,无疾病标签 |
| 2 | 只发布逐拍步幅时长与人口学表,原始压力波形从未发布 |
| 3 | 与 gaitdb、gaitndd 同门不同库,三者各占年龄轴或病种维度的一段 |
| 4 | Group 列有七行空缺,分组要自己按 age-months 划 |
| 5 | 体量不到两兆,适合做方法验证与正常参照,不适合训练大模型 |
编辑说明
核验方式:本页所有规模与结构数字取自 PhysioNet 官方页面、data 目录内的文件列表与 table.csv,发育结论取自论文摘要。逐拍数值仅以受试者 1 号作结构示例,未做全库统计。年龄口径存在两套:页面按月,论文按整岁,正文并列呈现。未覆盖的内容包括:每段行走的确切时长、着地判定算法细节、受试者招募与筛选标准、原始足底压力信号。若后续页面或版本变动,以官方为准。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- ehgdb — 共享标签:生理信号 / 可穿戴传感 / 儿科
- fpcgdb — 共享标签:生理信号 / 可穿戴传感 / 儿科
- live-gaitneurokids — 共享标签:生理信号 / 步态与运动 / 可穿戴传感 / 儿科
- ppg-dalia — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- culm — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- nesfdb — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- plantar — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- wearable-device-dataset — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- semg-gait-31subjects — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
- pamap2 — 共享标签:生理信号 / 步态与运动 / 可穿戴传感
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

