如何在Python中合并存在From/To区间重叠的两个数据集?
解决同ID下区间重叠的数据集合并问题
核心思路
把每个ID对应的所有区间(df1+df2)的起止点提取出来,拆分成无重叠的细小区间,再逐个判断每个细小区间属于「仅df1覆盖」「仅df2覆盖」「两者重叠覆盖」,对应取数:重叠和仅df2的用df2数据,仅df1的用df1数据。
具体实现步骤(基于Pandas)
先假设你的数据集结构示例如下:
import pandas as pd # 示例数据 df1 = pd.DataFrame({ 'ID': ['A', 'A'], 'From': [1, 10], 'To': [8, 20], 'Var1': ['df1_1', 'df1_2'], 'Var2': ['v1', 'v2'] }) df2 = pd.DataFrame({ 'ID': ['A', 'A'], 'From': [5, 15], 'To': [12, 18], 'Var1': ['df2_1', 'df2_2'], 'Var3': ['v3', 'v4'] # df2独有的额外变量 })
1. 定义单ID区间处理函数
针对单个ID的子数据集,生成拆分后的细小区间并匹配对应数据:
def process_id_group(id_df1, id_df2): # 提取所有区间的起止点,去重后排序 all_points = sorted(set(id_df1[['From', 'To']].values.flatten().tolist() + id_df2[['From', 'To']].values.flatten().tolist())) # 生成无重叠的细小区间 intervals = [] for i in range(len(all_points)-1): start = all_points[i] end = all_points[i+1] if start == end: continue # 跳过空区间 intervals.append((start, end)) result_rows = [] # 遍历每个细小区间,匹配数据源 for start, end in intervals: # 判断该区间是否被df1覆盖 df1_match = (id_df1['From'] <= start) & (id_df1['To'] >= end) # 判断该区间是否被df2覆盖 df2_match = (id_df2['From'] <= start) & (id_df2['To'] >= end) if df2_match.any(): # 取df2中覆盖该区间的行,替换起止点为当前细小区间 row = id_df2[df2_match].iloc[0].copy() row['From'] = start row['To'] = end result_rows.append(row) elif df1_match.any(): # 取df1中覆盖该区间的行,替换起止点为当前细小区间 row = id_df1[df1_match].iloc[0].copy() row['From'] = start row['To'] = end result_rows.append(row) return pd.DataFrame(result_rows)
2. 按ID批量处理并合并结果
# 遍历所有唯一ID,逐个处理后合并 unique_ids = df1['ID'].unique() final_result = pd.DataFrame() for id_val in unique_ids: df1_sub = df1[df1['ID'] == id_val].reset_index(drop=True) df2_sub = df2[df2['ID'] == id_val].reset_index(drop=True) processed_data = process_id_group(df1_sub, df2_sub) final_result = pd.concat([final_result, processed_data], ignore_index=True) # 重置索引(可选) final_result = final_result.reset_index(drop=True)
结果说明
- 拆分后的区间会自动处理重叠部分,重叠区域直接使用df2的行数据(包括其额外变量)
- df1独有的区间保留原df1数据
- 同名变量(比如示例中的
Var1)会自动取df2的值,因为直接复用了df2的行记录
注意事项
- 如果一个细小区间被df1或df2的多行覆盖,当前逻辑默认取第一行,你可以根据实际需求调整(比如取最新行、合并多行列值等)
- 确保
From和To是数值/日期时间类型,日期类型的处理逻辑和数值完全一致,仅需保证数据格式为datetime64即可
内容的提问来源于stack exchange,提问作者Celeste Wilson
相关产品推荐
相关产品推荐

