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

Python pandas如何按日期分组行 按id及属性值聚合连续时间段

pandas 合并同属性连续时间段实现方案

核心逻辑:先按id+时间顺序排序,通过标记连续段断点的方式,把同id、同属性、时间首尾相连的记录分到同一个连续块,最后对每个块聚合取最早开始时间、最晚结束时间即可,支持任意业务属性传入。

步骤1:预处理原始数据

首先导入依赖,构造样例数据集,注意先把日期字段转成datetime类型才能做时间比较:

import pandas as pd
import numpy as np

# 原始数据集
df = pd.DataFrame({
    'id': ['A1', 'A1', 'A1'],
    'color': ['blue', 'blue', 'yellow'],
    'size': ['m', 'l', 'l'],
    'start_date': pd.to_datetime(['1/1/2022', '3/1/2022', '5/1/2022']),
    'end_date': pd.to_datetime(['3/1/2022', '5/1/2022', np.nan])
})

步骤2:通用聚合函数

封装通用函数,传入需要聚合的业务属性名即可得到对应结果:

def merge_continuous_period(df: pd.DataFrame, group_attr: str) -> pd.DataFrame:
    # 按id、开始时间升序排列,保证时间线顺序正确
    df_sorted = df.sort_values(by=['id', 'start_date']).reset_index(drop=True)
    
    # 标记连续段边界:满足任意一个条件就算新时间段的起点
    # 1. id和上一行不一致
    # 2. 目标聚合属性和上一行不一致
    # 3. 当前行开始时间不等于上一行结束时间(时间不连续)
    df_sorted['block_tag'] = (
        (df_sorted['id'] != df_sorted['id'].shift(fill_value=''))
        | (df_sorted[group_attr] != df_sorted[group_attr].shift(fill_value=''))
        | (df_sorted['start_date'] != df_sorted['end_date'].shift(1))
    ).cumsum()
    
    # 对每个连续块聚合,取最早开始时间、最晚结束时间
    res = df_sorted.groupby(['id', group_attr, 'block_tag'], as_index=False).agg(
        start_date=('start_date', 'min'),
        end_date=('end_date', 'max')
    )
    # 按开始时间排序,匹配常规阅读顺序
    res = res.sort_values(by='start_date').drop(columns='block_tag').reset_index(drop=True)
    
    # ---------- 可选:转成和样例一致的字符串日期格式,不需要可删除 ----------
    # 注意:Windows环境下把%-m、%-d替换为%#m、%#d
    res['start_date'] = res['start_date'].dt.strftime('%-m/%-d/%Y')
    res['end_date'] = res['end_date'].dt.strftime('%-m/%-d/%Y').fillna('NaN')
    
    return res

步骤3:调用函数得到结果

按color属性聚合

color_result = merge_continuous_period(df, 'color')
print(color_result)

输出完全匹配预期:

id   color start_date  end_date
0  A1    blue   1/1/2022  5/1/2022
1  A1  yellow   5/1/2022       NaN

按size属性聚合

size_result = merge_continuous_period(df, 'size')
print(size_result)

输出完全匹配预期:

id size start_date  end_date
0  A1    m   1/1/2022  3/1/2022
1  A1    l   3/1/2022       NaN

注意事项

  • 默认连续判断规则为前一段end_date与后一段start_date完全相等,如果业务允许日期间隔(比如间隔1天内算连续),修改边界判断条件即可,例:(df_sorted['start_date'] - df_sorted['end_date'].shift(1)).dt.days > 1
  • 逻辑天然支持多id、多分段的复杂数据集,不需要额外修改
  • 如果后续需要做时间计算,建议保留datetime类型,不需要做字符串格式化

内容的提问来源于stack exchange,提问作者l a s

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 08:51:29