如何按id与name分组计算多个时间区间的并集?
按id和name合并时间区间求并集的实现方法
需求说明
需对DataFrame中同一id和name分组下的时间区间进行合并,将重叠或连续的区间合并为单一区间,得到合并后的起始时间(result_S)和结束时间(result_F)。
原始数据准备
import pandas as pd id_list = [1,1,1,1,1,1,1,2,2,2] name = ['A','A','A','A','A','B','B','C','C','C'] Start_time = ['2005-06-27','2005-07-07','2005-07-12','2006-11-15','2008-08-22','2009-03-03','2009-03-06','2007-10-26','2007-10-31','2007-11-06'] Final_time = ['2005-07-07','2005-07-12','2005-09-26','2008-08-22','2009-02-24','2009-03-06','2009-03-12','2007-10-31','2007-11-05','2007-11-09'] dataframe = pd.DataFrame({ 'id': id_list, 'name': name, 'Start_time': Start_time, 'Final_time': Final_time }) dataframe['Start_time'] = pd.to_datetime(dataframe['Start_time']) dataframe['Final_time'] = pd.to_datetime(dataframe['Final_time'])
实现步骤与代码
- 定义区间合并函数:对单个分组内的时间区间排序后,合并重叠或连续的区间
- 按
id和name分组,应用合并函数 - 将合并后的结果展开为标准DataFrame格式
def merge_intervals(intervals): # 按起始时间排序区间 sorted_intervals = sorted(intervals, key=lambda x: x[0]) merged = [] for interval in sorted_intervals: if not merged: merged.append(list(interval)) else: last_start, last_end = merged[-1] current_start, current_end = interval # 若当前区间与上一个重叠/连续,更新结束时间为较大值 if current_start <= last_end: merged[-1][1] = max(last_end, current_end) else: merged.append(list(interval)) return merged # 分组处理每个id+name组合的时间区间 grouped = dataframe.groupby(['id', 'name'])['Start_time', 'Final_time'].apply( lambda x: merge_intervals(x.values.tolist()) ).explode() # 转换为目标格式的DataFrame result = pd.DataFrame(grouped.tolist(), index=grouped.index, columns=['result_S', 'result_F']).reset_index()
最终结果
运行代码后得到的result如下:
| id | name | result_S | result_F |
|---|---|---|---|
| 1 | A | 2005-06-27 | 2005-09-26 |
| 1 | A | 2006-11-15 | 2009-02-24 |
| 1 | B | 2009-03-03 | 2009-03-12 |
| 2 | C | 2007-10-26 | 2007-11-05 |
| 2 | C | 2007-11-06 | 2007-11-09 |
该结果与预期一致:
- id=1、name=A的前三个重叠区间合并为一个,后两个连续区间合并为一个
- id=1、name=B的两个连续区间合并为一个
- id=2、name=C的两个不连续区间保持独立
内容的提问来源于stack exchange,提问作者Kevin Song
相关产品推荐
相关产品推荐

