如何按名称分组,合并重叠时间区间并对values求和
Pandas按分组合并重叠时间区间并求和的实现
问题描述
给定包含name、time_start、time_end和values字段的DataFrame,需按name分组,将每组内重叠的时间区间合并为大区间,同时对合并后区间对应的values求和。
输入数据
import pandas as pd df1 = (pd.DataFrame({'name': ['a', 'a', 'a', 'b', 'b'], 'time_start': ['2000-01-01 00:01:12', '2000-01-01 00:01:14', '2000-01-01 00:03:12', '2000-01-01 00:05:12', '2000-01-01 00:05:16'], 'time_end': ['2000-01-01 00:01:18', '2000-01-01 00:01:16', '2000-01-01 00:03:24', '2000-01-01 00:05:40', '2000-01-01 00:05:18'], 'values':[20,30,40,20,5]}) .assign(time_start = lambda x: pd.to_datetime(x['time_start']), time_end = lambda x: pd.to_datetime(x['time_end'])))
预期输出
name time_start time_end values 0 a 2000-01-01 00:01:12 2000-01-01 00:01:18 50 1 a 2000-01-01 00:03:12 2000-01-01 00:03:24 40 2 b 2000-01-01 00:05:12 2000-01-01 00:05:40 25
实现代码
def merge_intervals(group): # 按起始时间排序,确保区间处理顺序正确 sorted_group = group.sort_values('time_start', ascending=True) merged = [] for _, row in sorted_group.iterrows(): if not merged: merged.append({ 'name': row['name'], 'time_start': row['time_start'], 'time_end': row['time_end'], 'values': row['values'] }) else: last_entry = merged[-1] # 判断当前区间是否与上一个合并区间重叠 if row['time_start'] <= last_entry['time_end']: # 合并区间:更新结束时间为两者最大值,累加values last_entry['time_end'] = max(last_entry['time_end'], row['time_end']) last_entry['values'] += row['values'] else: # 无重叠,直接添加新的区间条目 merged.append({ 'name': row['name'], 'time_start': row['time_start'], 'time_end': row['time_end'], 'values': row['values'] }) return pd.DataFrame(merged) # 分组处理并重置索引 result = df1.groupby('name', group_keys=False).apply(merge_intervals).reset_index(drop=True) print(result)
代码说明
- 排序分组:每个分组先按
time_start排序,保证按时间顺序处理区间,避免因乱序导致合并逻辑出错; - 合并逻辑:遍历排序后的区间,维护一个合并后的区间列表。如果当前区间与列表最后一个区间重叠(当前起始时间≤上一个区间的结束时间),则合并两者——取较大的结束时间,同时累加对应
values;若不重叠,直接将当前区间作为新条目加入列表; - 分组应用:通过
groupby对每个name分组,应用自定义合并函数,最后重置索引得到规整的结果。
内容的提问来源于stack exchange,提问作者ferrelwill
相关产品推荐
相关产品推荐

