
本文介绍如何基于事件类型识别并聚合连续的“步态事件段”(stepping bouts),即对 dataframe 中相邻且类型相同的行(如 event type == 2)按 id 和日期内连续块分别求 duration 总和。
本文介绍如何基于事件类型识别并聚合连续的“步态事件段”(stepping bouts),即对 dataframe 中相邻且类型相同的行(如 event type == 2)按 id 和日期内连续块分别求 duration 总和。
在加速度计数据分析中,常需将离散的步态事件(如 Event Type == 2)按时间连续性聚合成“bouts”(行为段),再对每段的持续时间(Duration)求和——而非简单按事件类型全局分组。关键难点在于:同一 ID 同一日内可能包含多个不连续的步态段(例如:站立→步行→静坐→步行),必须区分这些独立片段。
核心思路:构建“连续段标识符”
Pandas 本身不提供原生的“连续组识别”函数,但可通过布尔掩码 + 累计求和巧妙构造分组键:
- 标记目标事件:用 df[‘Event Type’].eq(2) 得到布尔序列 m;
- 识别段边界:~m 表示非步态事件(即段间分隔点),对其按 ID 分组后使用 cumsum(),可为每个 ID 内的每一段步态事件生成唯一递增编号;
- 组合分组键:将 ID 与该编号联合分组,即可精准捕获每个 ID 下所有独立的步态段。
⚠️ 注意:若需进一步限定“同日内连续段”,应在分组前先添加日期列(如 Date)到 groupby 键中,避免跨日误合并。
完整实现代码
import pandas as pd
# 示例数据(含跨日及多段步态)
df = pd.DataFrame({
'ID': [1885]*13,
'Date': ['2021-06-29'] + ['2021-07-07']*12,
'Event Type': [4.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 1.0, 2.0, 2.0, 2.0, 1.0],
'Duration': [31208.5, 1.1, 3.2, 3.5, 4.3, 3.7, 1.2, 1.1, 1.0, 3.7, 1.2, 1.1, 1.0]
})
# 步骤1:筛选步态事件(Event Type == 2)
m = df['Event Type'].eq(2)
# 步骤2:构造连续段ID(按ID分组,对非步态事件累计求和)
segment_id = (~m).groupby(df['ID']).cumsum()
# 步骤3:按ID + 段ID分组,聚合Duration总和
bouts = (df[m]
.assign(segment_id=segment_id)
.groupby(['ID', 'segment_id'], as_index=False)
['Duration'].sum()
.drop(columns='segment_id'))
print(bouts)
输出:
ID Duration 0 1885 18.1 1 1885 6.0
扩展建议:支持多维度约束(如日期+ID)
若需确保“连续段”严格限定在同一日期内(防止跨日步态被错误合并),请将 Date 列加入分组逻辑:
# 更严谨的版本:按 ID + Date 联合分组识别段
m = df['Event Type'].eq(2)
# 对每个 ID-Date 组合独立计算段ID
segment_id = (~m).groupby([df['ID'], df['Date']]).cumsum()
bouts_daily = (df[m]
.assign(segment_id=segment_id)
.groupby(['ID', 'Date', 'segment_id'], as_index=False)
['Duration'].sum()
.drop(columns='segment_id'))
小结
- ✅ 此方法无需循环或 itertools.groupby,纯向量化,高效处理数十万行数据;
- ✅ (~m).groupby(…).cumsum() 是识别连续段的核心技巧,适用于任意“状态切换型”分组场景;
- ✅ 后续可轻松对 bouts 结果做统计分析,如 bouts.groupby(‘ID’)[‘Duration’].agg([‘mean’, ‘count’, ‘std’]) 计算平均步态段时长、频次等指标。
掌握该模式后,你不仅能处理步态分析,还可迁移至睡眠分期、运动周期、设备运行时段等各类“连续行为段识别”任务。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/xitongjiaocheng/126785.html