
本文介绍如何使用 Pandas 对 DataFrame 按时间/序号维度动态累积统计分类活动(如运动项目),确保每一行反映截至该时间点的精确累计频次,适用于学生活动记录、用户行为轨迹等场景。
本文介绍如何使用 pandes 对 dataframe 按时间/序号维度动态累积统计分类活动(如运动项目),确保每一行反映截至该时间点的精确累计频次,适用于学生活动记录、用户行为轨迹等场景。
在分析时序型分类行为数据(例如学生每年选择的运动项目)时,一个常见但易被忽视的需求是:每一行不仅记录当次选择,还需体现“截至当前访问次数”的历史累计经验。例如,Mike 第 3 年首次尝试羽毛球,那么从第 3 行开始,Badminton 列应变为 1;第 4 行仍为 1(尚未再次选择),第 5 行若选择游泳,则 Swimming 变为 1,而 Football 和 Badminton 保持已有累计值(3 和 1)。这本质上是一个按分组(如 Name)+ 按自然顺序(Nr)的累计计数问题,而非简单的一次性赋值。
核心思路是:将 Activity 列进行 one-hot 编码,生成临时的二值矩阵(每列对应一个运动项目,选中则为 1,否则为 0),再按学生分组(groupby('Name'))对各项目列执行 cumsum() —— 这能严格保证累计值随行序递增,且仅累加该学生自身的记录。
以下是完整实现代码:
import pandas as pd
# 示例输入数据
df = pd.DataFrame({
'Name': ['Mike', 'Mike', 'Mike', 'Mike', 'Mike'],
'Nr': [1, 2, 3, 4, 5],
'Activity': ['Football', 'Football', 'Badminton', 'Football', 'Swimming'],
'Football': [0, 0, 0, 0, 0],
'Badminton': [0, 0, 0, 0, 0],
'Swimming': [0, 0, 0, 0, 0]
})
# 方案一:原地更新(要求目标列已存在)
df.update(pd.get_dummies(df['Activity']).groupby(df['Name']).cumsum())
# 方案二:若原始 DataFrame 不含 Sport 列,直接拼接新列
# out = df.join(pd.get_dummies(df['Activity']).groupby(df['Name']).cumsum())✅ 关键说明:
- pd.get_dummies(df['Activity']) 将 Activity 转为宽表形式(如 Football, Badminton, Swimming 各一列,值为 0/1);
- .groupby(df['Name']).cumsum() 确保每个学生独立累计,且严格按原始 DataFrame 行顺序(即 Nr 升序)累加,无需显式排序——前提是你的数据已按 Nr 排好;
- df.update(...) 是就地更新,仅覆盖同名列,不改变原始结构;join 方式则更安全,适合列未预定义的场景。
⚠️ 注意事项:
- 若 Nr 列未排序,请先执行 df = df.sort_values(['Name', 'Nr']).reset_index(drop=True),否则 cumsum() 结果将错乱;
- 若 Activity 存在多值(如 'Football|Swimming'),请改用 df['Activity'].str.get_dummies(sep='|');
- 此方法天然支持多人(如多个 Name),groupby('Name') 自动隔离各人累计路径;
- 性能高效,避免 apply 或循环,充分利用 Pandas 向量化操作。
该模式不仅适用于夏令营运动统计,还可拓展至用户产品功能使用频次追踪、员工技能认证累积、设备维护历史汇总等所有「分类行为 + 时间序列 + 分组累计」场景。


















