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

如何基于重叠日期在Python中合并两个DataFrame

基于日期区间交集合并DataFrame的解决方案

核心思路

按Key分组,提取每个Key下所有涉及的日期节点(包括两个DataFrame的起始、结束日期),将这些节点排序后生成连续的时间分段区间,再逐个区间匹配对应的char1和char2,最终得到分段后的匹配结果。

具体实现步骤

1. 日期格式转换

先把两个DataFrame里的日期字符串统一转成datetime类型,避免字符串比较的误差:

import pandas as pd

# 定义日期解析格式
date_format = "%d/%m/%Y"

# 处理df1的日期列
df1['in_date'] = pd.to_datetime(df1['in_date'], format=date_format)
df1['out_date'] = pd.to_datetime(df1['out_date'], format=date_format)

# 处理df2的日期列
df2['st_date'] = pd.to_datetime(df2['st_date'], format=date_format)
df2['end_date'] = pd.to_datetime(df2['end_date'], format=date_format)

2. 生成每个Key的时间分割点

对每个Key,收集df1的in_date、out_date和df2的st_date、end_date,去重后排序,得到用于分割时间的节点列表:

# 合并两个df的日期数据,按Key分组收集所有日期
all_dates = pd.concat([
    df1[['Key', 'in_date']].rename(columns={'in_date': 'date'}),
    df1[['Key', 'out_date']].rename(columns={'out_date': 'date'}),
    df2[['Key', 'st_date']].rename(columns={'st_date': 'date'}),
    df2[['Key', 'end_date']].rename(columns={'end_date': 'date'})
])

# 按Key分组,对日期去重并排序
split_dates = all_dates.groupby('Key')['date'].apply(lambda x: sorted(x.unique())).reset_index()

3. 生成连续时间区间

基于分割点,为每个Key生成连续的start和end区间:

# 生成区间函数
def create_intervals(dates):
    intervals = []
    for i in range(len(dates)-1):
        intervals.append({'start': dates[i], 'end': dates[i+1]})
    return pd.DataFrame(intervals)

# 对每个Key生成区间
interval_df = split_dates.explode('date', ignore_index=False)
interval_df = interval_df.groupby('Key').apply(lambda x: create_intervals(x['date'])).reset_index()
interval_df = interval_df.drop(columns='level_1').rename(columns={'Key': 'key'})

4. 匹配每个区间对应的char1和char2

编写函数,对每个区间,找到df1中完全包含该区间的char1(如果没有则为NaN),同理匹配df2的char2:

def get_char1(row, df1):
    # 筛选当前key下,in_date <= start 且 out_date >= end的记录
    mask = (df1['Key'] == row['key']) & (df1['in_date'] <= row['start']) & (df1['out_date'] >= row['end'])
    res = df1.loc[mask, 'char1'].unique()
    return res[0] if len(res) > 0 else pd.NA

def get_char2(row, df2):
    mask = (df2['Key'] == row['key']) & (df2['st_date'] <= row['start']) & (df2['end_date'] >= row['end'])
    res = df2.loc[mask, 'char2'].unique()
    return res[0] if len(res) > 0 else pd.NA

# 应用函数匹配特征
interval_df['char1'] = interval_df.apply(get_char1, args=(df1,), axis=1)
interval_df['char2'] = interval_df.apply(get_char2, args=(df2,), axis=1)

5. 格式化日期输出(可选)

如果需要把datetime类型转回原字符串格式:

interval_df['start'] = interval_df['start'].dt.strftime(date_format)
interval_df['end'] = interval_df['end'].dt.strftime(date_format)

最终结果

运行完上述代码后,interval_df的结构和内容就会和你期望的结果一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:39:55