基于日期分组的Pandas时序数据:生成value变化时每日重置的序列列
问题
我有跨多天的时序数据,需要生成序列列(每次value值变化时创建序列标识)。已经实现了不使用groupby的序列生成,但不知道怎么把逻辑应用到按日期分组的数据上。
数据结构如下:
index timestamp value 0 1684713605000 1 1 1684713610000 1 2 1684713611000 1 3 1684713614000 0 4 1684713615000 0 5 1684713616000 0 6 1684713619000 1 7 1684713620000 1 8 1684713621000 1 9 1684832896000 1 10 1684832897000 1 11 1684832898000 1 12 1684832901000 0 13 1684832902000 0 14 1684832903000 0 15 1684832906000 1 16 1684832907000 1 17 1684832908000 1
timestamp列不保证连续,但通常每日每秒一条记录。需要生成的seq列在value变化时递增,且每日结束后重置为0。
当前使用的序列生成代码:
subset = df[["value"]].copy() subset["change"] = (subset["value"].shift() != subset["value"]) * 1 subset["seq"] = subset["change"].cumsum(axis = 0) - 1 df["seq"] = subset["seq"]
已经通过以下代码创建日期分组:
subset = df[["timestamp", "value"]].copy() subset["date"] = pd.to_datetime(subset["timestamp"], unit="ms", origin="unix").dt.date g = subset.groupby("date")
但不清楚后续操作,期望得到的结果示例如下:
index timestamp value seq 0 1684713605000 1 0 1 1684713610000 1 0 2 1684713611000 1 0 3 1684713614000 0 1 4 1684713615000 0 1 5 1684713616000 0 1 6 1684713619000 1 2 7 1684713620000 1 2 8 1684713621000 1 2 9 1684832896000 1 0 <-- 新日期的第一条记录 10 1684832897000 1 0 11 1684832898000 1 0 12 1684832901000 0 1 13 1684832902000 0 1 14 1684832903000 0 1 15 1684832906000 1 2 16 1684832907000 1 2 17 1684832908000 1 2
解决方案
核心思路是按日期分组后,在每个分组内独立执行你原来的序列生成逻辑,最后合并结果即可。可以用groupby().apply()实现,具体步骤如下:
- 给原数据添加日期列(也可在分组时直接处理,无需提前存到临时表)
- 定义函数,接收单个分组数据,在内部生成seq列
- 用
groupby().apply()将函数应用到每个日期分组,最后合并回原数据
完整代码如下:
import pandas as pd # 假设原始数据为df df = pd.DataFrame({ 'timestamp': [1684713605000, 1684713610000, 1684713611000, 1684713614000, 1684713615000, 1684713616000, 1684713619000, 1684713620000, 1684713621000, 1684832896000, 1684832897000, 1684832898000, 1684832901000, 1684832902000, 1684832903000, 1684832906000, 1684832907000, 1684832908000], 'value': [1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1] }) # 定义分组内生成seq的函数 def generate_seq(group): group = group.copy() # 计算分组内的value变化标记,shift()仅在当前分组内偏移 group['change'] = (group['value'].shift() != group['value']).astype(int) # 组内累加并减1,实现从0开始的序列 group['seq'] = group['change'].cumsum() - 1 return group # 添加日期列并分组处理 df['date'] = pd.to_datetime(df['timestamp'], unit='ms', origin='unix').dt.date df = df.groupby('date').apply(generate_seq).reset_index(drop=True) # 可选:移除临时的date和change列 df = df.drop(['date', 'change'], axis=1) print(df)
代码说明
generate_seq函数:针对单个日期分组执行原序列生成逻辑,shift()和cumsum()被限制在当前日期范围内,自然实现每日重置。groupby().apply():自动将每个分组传入函数处理,处理后合并所有分组结果,保留原始数据顺序。- 最后可删除临时的
date和change列,得到目标结构。
运行后输出结果与期望示例一致,每个日期内的seq从0开始,每次value变化时递增。
内容的提问来源于stack exchange,提问作者niko
相关产品推荐
相关产品推荐

