如何基于时间间隔对Pandas DataFrame的行进行分组合并?
按时间间隔分组合并Pandas DataFrame行
需要基于行之间的时间差对Pandas DataFrame的行进行分组:若两条记录的时间间隔小于30天则归为同一组,否则视为独立事件;每组的start取组内第一条记录的start,end取组内最后一条记录的end。
示例
原DataFrame
| id | start | end |
|---|---|---|
| 1 | 2023-08-10 | 2023-09-01 |
| 1 | 2023-09-20 | 2023-10-14 |
| 1 | 2023-11-20 | 2023-12-27 |
| 2 | 2023-08-15 | 2023-09-05 |
| 2 | 2023-09-20 | 2023-10-14 |
| 2 | 2023-11-01 | 2023-12-20 |
处理后DataFrame
| id | start | end |
|---|---|---|
| 1 | 2023-08-10 | 2023-10-14 |
| 1 | 2023-11-20 | 2023-12-27 |
| 2 | 2023-08-15 | 2023-12-20 |
说明
以id=1的记录为例:第二条记录的start与第一条的end间隔为19天(小于30天),故合并;第三条与第二条间隔超过30天,视为独立事件。
原始DataFrame代码
import pandas as pd df = pd.DataFrame({ 'id': [1, 2, 1, 1, 2, 2], 'start': ['2023-08-10', '2023-08-15', '2023-09-20', '2023-11-20', '2023-09-20', '2023-11-01'], 'end': ['2023-09-01', '2023-09-05', '2023-10-14', '2023-12-27', '2023-10-14', '2023-12-20'] })
解决方案
步骤说明
- 将
start和end列转换为日期时间类型,方便计算时间差 - 按
id分组,对每组内的记录按start排序 - 计算当前行的
start与上一行的end的时间差,判断是否大于等于30天 - 根据时间差生成组标识,将连续满足间隔<30天的记录归为同一组
- 按
id和组标识聚合,取每组的第一条start和最后一条end
代码实现
# 转换日期类型 df['start'] = pd.to_datetime(df['start']) df['end'] = pd.to_datetime(df['end']) # 按id分组处理 def group_by_interval(group): # 按start排序 group_sorted = group.sort_values('start') # 计算时间差:当前start - 上一行end time_diff = group_sorted['start'] - group_sorted['end'].shift(1) # 标记需要新分组的行(首次行或间隔>=30天) new_group = time_diff >= pd.Timedelta(days=30) new_group.iloc[0] = True # 第一行必为新组开头 # 生成组编号 group_sorted['group_id'] = new_group.cumsum() # 聚合 return group_sorted.groupby(['id', 'group_id']).agg( start=('start', 'first'), end=('end', 'last') ).reset_index(drop=True) # 应用函数并合并结果 result = df.groupby('id', group_keys=False).apply(group_by_interval).reset_index() # 移除多余的index列 result = result.drop('index', axis=1) print(result)
输出结果
id start end 0 1 2023-08-10 2023-10-14 1 1 2023-11-20 2023-12-27 2 2 2023-08-15 2023-12-20
内容的提问来源于stack exchange,提问作者Grigoris Papapostolou
相关产品推荐
相关产品推荐

