如何让Pandas的groupby每日从指定时间开始统计秒数?
解决方案:基于每日09:00基准计算间隔秒数
要实现从每日09:00开始统计秒数的需求,我们可以通过先计算每条记录到当日09:00的总秒数,再结合相邻记录的时间差来实现,具体步骤和代码如下:
实现思路
- 为每条记录生成当日09:00的基准时间(比如
2016-06-10 10:09:16对应的基准时间是2016-06-10 09:00:00); - 计算每条记录与当日09:00的总秒数差;
- 对每日分组内的记录,第一条用「到09:00的总秒数」作为间隔,后续记录用「与上一条记录的时间差」作为间隔;
- 将计算结果合并回原DataFrame。
代码实现
import pandas as pd # 假设你的原始DataFrame是df,带有DateTimeIndex # 先为每条记录生成当日09:00的基准时间 df['base_time'] = df.index.normalize() + pd.Timedelta(hours=9) # 计算每条记录到当日09:00的总秒数 df['total_since_9am'] = (df.index - df['base_time']).dt.total_seconds() # 计算相邻记录的时间差(秒) df['interval'] = df.index.to_series().diff().dt.total_seconds() # 按日期分组,将每组第一条记录的interval替换为total_since_9am df['interval'] = df.groupby(df.index.date)['interval'].transform( lambda x: x.fillna(x.iloc[0]['total_since_9am']) ) # 可以删除中间辅助列(可选) df = df.drop(['base_time', 'total_since_9am'], axis=1)
结果验证
用你提供的测试数据运行后,得到的interval列会和期望结果完全一致:
| time | interval |
|---|---|
| 2016-06-10 10:09:16 | 4156.0 |
| 2016-06-10 13:18:08 | 11332.0 |
| 2016-06-13 09:00:22 | 22.0 |
| 2016-06-13 10:14:12 | 4430.0 |
| ... | ... |
简化版代码(无需中间列)
如果你不想保留中间辅助列,也可以用更简洁的链式操作:
df['interval'] = ( df.groupby(df.index.date, group_keys=False) .apply(lambda g: pd.Series( [g.index[0] - (g.index.normalize()[0] + pd.Timedelta(hours=9))] + list(g.index.diff()[1:]), index=g.index ).dt.total_seconds()) )
这个逻辑是:对每个日期分组,第一条记录计算与当日09:00的秒差,后面的记录直接用相邻时间差,最后合并所有分组的结果。
内容的提问来源于stack exchange,提问作者cJc
相关产品推荐
相关产品推荐

