如何基于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()
错误原因
- 语法错误:分组字段列表里的
"person缺少闭合引号 - 逻辑错误:按
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
相关产品推荐
相关产品推荐

