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
相关产品推荐
相关产品推荐

