You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中合并存在日期重叠的两个DataFrame?

处理Pandas中带重叠日期的DataFrame合并问题

要实现两个带重叠日期区间的DataFrame合并,核心思路是先拆分出所有不重叠的连续日期区间,再为每个区间匹配对应的数据值。以下是具体步骤:

步骤1:预处理日期列

首先将原始数据中的日期字符串转为Pandas的datetime类型,方便后续时间运算:

import pandas as pd

# 构造示例数据
dds = pd.DataFrame({
    'STATE': ['Alabama', 'Alabama', 'Alabama'],
    'START_DATE': ['04/01/2021', '06/16/2021', '08/13/2021'],
    'END_DATE': ['06/15/2021', '08/12/2021', '09/30/2021'],
    'data_val': ['x', 'y', 'z']
})

ops = pd.DataFrame({
    'STATE': ['Alabama', 'Alabama', 'Alaska'],
    'START_DATE': ['05/01/2021', '06/01/2021', '04/01/2021'],
    'END_DATE': ['05/31/2021', '12/01/2021', '08/01/2021'],
    'data_val2': ['ab', 'cd', 'ez']
})

# 转换日期列为datetime类型,自动推断格式
for df in [dds, ops]:
    df['START_DATE'] = pd.to_datetime(df['START_DATE'], infer_datetime_format=True)
    df['END_DATE'] = pd.to_datetime(df['END_DATE'], infer_datetime_format=True)

注:原始ops数据中的31/05/2021应为输入格式错误,调整为05/31/2021以匹配月/日/年的统一格式。

步骤2:拆分并匹配日期区间

按STATE分组,收集所有原始区间的起止点(包括区间结束日+1天),拆分出所有不重叠的连续小区间,再为每个小区间匹配对应的data_val和data_val2:

result_list = []

# 按STATE遍历处理每个州的数据
for state in pd.concat([dds['STATE'], ops['STATE']]).unique():
    # 获取当前州的所有日期分割点:包含原始区间的开始日、结束日+1天
    dds_dates = dds[dds['STATE'] == state][['START_DATE', 'END_DATE']]
    ops_dates = ops[ops['STATE'] == state][['START_DATE', 'END_DATE']]
    
    split_dates = sorted(set(
        dds_dates['START_DATE'].tolist() +
        (dds_dates['END_DATE'] + pd.Timedelta(days=1)).tolist() +
        ops_dates['START_DATE'].tolist() +
        (ops_dates['END_DATE'] + pd.Timedelta(days=1)).tolist()
    ))
    
    # 生成每个连续的小区间
    for start, next_start in zip(split_dates[:-1], split_dates[1:]):
        end = next_start - pd.Timedelta(days=1)
        if start > end:
            continue
        
        # 匹配当前区间对应的data_val
        dds_match = dds[(dds['STATE'] == state) & 
                        (dds['START_DATE'] <= start) & 
                        (dds['END_DATE'] >= end)]
        data_val = dds_match['data_val'].iloc[0] if not dds_match.empty else None
        
        # 匹配当前区间对应的data_val2
        ops_match = ops[(ops['STATE'] == state) & 
                        (ops['START_DATE'] <= start) & 
                        (ops['END_DATE'] >= end)]
        data_val2 = ops_match['data_val2'].iloc[0] if not ops_match.empty else None
        
        result_list.append({
            'STATE': state,
            'START_DATE': start,
            'END_DATE': end,
            'data_val': data_val,
            'data_val2': data_val2
        })

# 转换为结果DataFrame
result = pd.DataFrame(result_list)

步骤3:格式化输出

将日期转为指定格式,空值替换为NULL,匹配期望输出:

# 格式化日期为MM/DD/YYYY
result['START_DATE'] = result['START_DATE'].dt.strftime('%m/%d/%Y')
result['END_DATE'] = result['END_DATE'].dt.strftime('%m/%d/%Y')

# 替换空值为NULL
result = result.fillna('NULL')

print(result)

运行后输出结果与期望一致:

STATE START_DATE   END_DATE data_val data_val2
0  Alabama  04/01/2021  04/30/2021        x      NULL
1  Alabama  05/01/2021  05/31/2021        x        ab
2  Alabama  06/01/2021  06/15/2021        x        cd
3  Alabama  06/16/2021  08/12/2021        y        cd
4  Alabama  08/13/2021  09/30/2021        z        cd
5  Alabama  10/01/2021  12/01/2021     NULL        cd
6   Alaska  04/01/2021  08/01/2021     NULL        ez

内容的提问来源于stack exchange,提问作者NEWBIE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:00:00