You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于10分钟间隔迭代计算pandas groupby差值生成新分组列

需求说明
  • 现有已按person、time_bought排序的DataFrame,已提前根据行前后记录是否为fruit生成了group列。
  • 需要新增new_group列,分组规则:同用户下相邻的fruit类购买记录,时间差在10分钟内归为同一组,超过10分钟则新建分组,非fruit类记录归属到它之前最近的fruit记录所在分组。

示例数据如下:

person   time_bought  product  group  new_group
abby     2:21         fruit     1       1
abby     2:24         other     
abby     2:25         fruit     2       1  (2.25 is within 10 minutes of 2.21 so part of same group)
abby     10:35        fruit     2       2  
abby     10:40        other
abby     10:42        fruit     3       2  (10.42 is within 10 minutes of 10.35)
abby     10:53        fruit     4       3  (10.53 is not within 10 minutes of 10.42)
abby     11:04        fruit     d
barry    12:00        fruit     1

之前尝试的代码未得到预期结果:

m= df.groupby(["person", "group"]).time_bought.diff()
df["new_group"] = df.groupby(["person, "group"]).mask(m).ffill()
错误原因
  1. 语法错误:分组字段列表里的"person缺少闭合引号
  2. 逻辑错误:按person+group分组计算时间差不符合需求,分组判断只需要参考同用户下所有fruit记录的时间间隔,和提前生成的group列无关;且mask、ffill的调用逻辑错误,没有正确生成分组递增的序号。
实现代码
import pandas as pd

# 先将时间字符串转为可计算差值的时间格式,默认按同一天时间处理
df['time_bought'] = pd.to_datetime(df['time_bought'], format='%H:%M')

# 标记fruit类记录
fruit_row_mask = df['product'] == 'fruit'
# 按用户分组,计算每条fruit记录和上一条fruit记录的时间差
adjacent_fruit_diff = df[fruit_row_mask].groupby('person')['time_bought'].diff()

# 时间差超过10分钟则标记为新分组起点,按用户单独累加生成分组序号,从1开始计数
df.loc[fruit_row_mask, 'new_group'] = (
    (adjacent_fruit_diff > pd.Timedelta(minutes=10))
    .groupby(df.loc[fruit_row_mask, 'person'])
    .cumsum() + 1
)

# 同用户下向下填充分组序号,给中间的非fruit记录匹配对应分组
df['new_group'] = df.groupby('person')['new_group'].ffill()

# 如需将时间列转回原字符串格式,可执行以下语句
df['time_bought'] = df['time_bought'].dt.strftime('%H:%M')

运行后结果和示例给出的预期完全匹配:同用户下相邻fruit间隔小于10分钟同组,间隔超10分钟自动新建组,非fruit行自动继承前序最近fruit的分组号。


内容的提问来源于stack exchange,提问作者asd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:24:21