如何在Python中对存在区间重叠的列值进行求和合并
这是个很常见的区间重叠合并+聚合需求,我用Python的Pandas来实现你想要的效果,步骤和代码如下:
原始输入数据
| id | group | start | end | stg |
|---|---|---|---|---|
| 0 | ZZ | 0 | 25 | 5.0 |
| 1 | ZZ | 10 | 65 | 7.0 |
| 2 | ZZ | 30 | 50 | 2.0 |
| 3 | ZZ | 50 | 60 | 3.0 |
| 4 | BB | 0 | 2 | 5.6 |
| 5 | BB | 5 | 8 | 6.6 |
| 6 | BB | 8 | 13 | 18.0 |
需求说明
针对每个分组(ZZ/BB),拆分重叠的[start, end]区间,在每个独立的不重叠子区间内,对覆盖该区间的所有原始行的stg值求和,生成新的区间及对应的stg总和。
代码实现
import pandas as pd # 加载原始数据 df = pd.DataFrame({ 'id': [0,1,2,3,4,5,6], 'group': ['ZZ','ZZ','ZZ','ZZ','BB','BB','BB'], 'start': [0,10,30,50,0,5,8], 'end': [25,65,50,60,2,8,13], 'stg': [5.0,7.0,2.0,3.0,5.6,6.6,18.0] }) # 定义单个分组的处理函数 def process_single_group(group_data): # 提取所有区间端点,去重后排序 all_points = sorted(set(group_data['start'].tolist() + group_data['end'].tolist())) # 生成所有不重叠的子区间 sub_intervals = [(all_points[i], all_points[i+1]) for i in range(len(all_points)-1)] processed_rows = [] for sub_start, sub_end in sub_intervals: # 筛选出和当前子区间有重叠的原始行 overlap_mask = (group_data['start'] < sub_end) & (group_data['end'] > sub_start) total_stg = group_data.loc[overlap_mask, 'stg'].sum() # 只保留有stg值的区间(跳过无覆盖的空区间) if total_stg > 0: processed_rows.append({ 'group': group_data['group'].iloc[0], 'start': sub_start, 'end': sub_end, 'stg': total_stg }) return pd.DataFrame(processed_rows) # 按分组处理并合并结果 final_result = df.groupby('group').apply(process_single_group).reset_index(drop=True) # 添加新的id列 final_result.insert(0, 'id', range(len(final_result))) # 打印结果 print(final_result.to_string(index=False))
运行结果
id group start end stg 0 ZZ 0 10 5.0 1 ZZ 10 25 12.0 2 ZZ 25 30 7.0 3 ZZ 30 50 9.0 4 ZZ 50 60 10.0 5 ZZ 60 65 7.0 6 BB 0 2 5.6 7 BB 5 8 6.6 8 BB 8 13 18.0
逻辑说明
- 提取端点:把每个分组的所有start和end值收集起来,去重排序后得到所有的分界点,这些点将整个时间轴切成了不重叠的小片段。
- 区间匹配:对每个小片段,检查哪些原始行的区间和它有重叠(只要原始区间和子区间有交集就算覆盖),然后把这些行的stg求和。
- 过滤空区间:如果某个子区间没有任何原始行覆盖,就跳过它,避免生成stg为0的无效行。
内容的提问来源于stack exchange,提问作者geek2000
相关产品推荐
相关产品推荐

