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

如何合并Pandas DataFrame产品记录:按状态及日期间隔聚合

需求与实现方案

原始数据

ProductStatusStart_DateEnd_Date
BananaGood2000-01-012000-12-31
AppleGood2000-01-012000-12-31
AppleGood2001-01-012001-12-31
AppleGood2002-01-012023-09-28
BananaBad2001-01-012001-12-31
BananaGood2002-01-01NaT
OrangeGood2001-01-012001-12-31
OrangeGood2002-02-01NaT

需求

  • 合并无状态变化且时间连续的产品记录,保留最小Start_Date和最大End_Date
  • 状态切换时,单独保留该状态段的聚合记录
  • 相邻记录存在日期间隔时,保留各段独立记录

期望输出

ProductStatusStart_DateEnd_Date
AppleGood2000-01-012023-09-28
BananaGood2000-01-012000-12-31
BananaBad2001-01-012001-12-31
BananaGood2002-01-01NaT
OrangeGood2001-01-012001-12-31
OrangeGood2002-02-01NaT

实现代码

import pandas as pd

# 1. 构建原始DataFrame
data = {
    'Product': ['Banana', 'Apple', 'Apple', 'Apple', 'Banana', 'Banana', 'Orange', 'Orange'],
    'Status': ['Good', 'Good', 'Good', 'Good', 'Bad', 'Good', 'Good', 'Good'],
    'Start_Date': ['2000-01-01', '2000-01-01', '2001-01-01', '2002-01-01', '2001-01-01', '2002-01-01', '2001-01-01', '2002-02-01'],
    'End_Date': ['2000-12-31', '2000-12-31', '2001-12-31', '2023-09-28', '2001-12-31', pd.NaT, '2001-12-31', pd.NaT]
}
df = pd.DataFrame(data)

# 2. 转换日期列为datetime类型,便于时间运算
df['Start_Date'] = pd.to_datetime(df['Start_Date'])
df['End_Date'] = pd.to_datetime(df['End_Date'])

# 3. 按产品和开始日期排序,确保时间顺序正确
df_sorted = df.sort_values(['Product', 'Start_Date']).reset_index(drop=True)

# 4. 生成分组标识:满足任一条件则开启新分组
# - 产品切换(冗余但保证鲁棒性)
# - 状态切换
# - 当前记录的开始日期不是上一条记录结束日期的次日(存在间隔)
df_sorted['group_key'] = (
    (df_sorted['Product'] != df_sorted['Product'].shift()) 
    | (df_sorted['Status'] != df_sorted['Status'].shift()) 
    | (df_sorted['Start_Date'] != df_sorted['End_Date'].shift() + pd.Timedelta(days=1))
).cumsum()

# 5. 聚合分组,取每组的最小开始日期和最大结束日期
result = df_sorted.groupby(['Product', 'Status', 'group_key'], as_index=False).agg(
    Start_Date=('Start_Date', 'min'),
    End_Date=('End_Date', 'max')
).drop(columns='group_key')

# 6. 按产品和开始日期排序,匹配期望输出顺序
result = result.sort_values(['Product', 'Start_Date']).reset_index(drop=True)

print(result)

代码说明

  1. 日期转换:将字符串日期转为datetime类型,支持后续的时间差计算;
  2. 排序:确保每个产品的记录按时间顺序排列,保证分组逻辑的正确性;
  3. 分组标识:通过cumsum()给满足拆分条件的记录分配不同组ID,实现"连续同状态且无间隔则合并"的逻辑;
  4. 聚合:对每个分组取最小开始日期和最大结束日期,完成合并;
  5. 最终排序:调整输出顺序,与期望结果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:47:23