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

时间序列分组需求:按连续阶段统计项目阶段起止日期

按连续阶段统计项目起止日期的解决方案

问题背景

现有项目阶段时间数据如下:

projectstagedate
33New3-sep-2022
33New10-sep-2022
33Preparation11-sep-2022
33Preparation21-sep-2022
33Preparation23-sep-2022
33New24-sep-2022
33New28-sep-2022

需要统计每个连续阶段的起止日期,期望输出:

projectstagebegin_stageend_stage
33New3-sep-202210-sep-2022
33Preparation11-sep-202223-sep-2022
33New24-sep-202228-sep-2022

注意:项目在9月24日回到New阶段,需将该阶段拆分为两次统计。

尝试了以下代码,但会把所有New阶段合并,不符合需求:

min_df = df.groupby(['project', 'stage'], as_index=False)['date'].agg('min')
max_df = df.groupby(['project', 'stage'], as_index=False)['date'].agg('max')

df = pd.merge(min_df, max_df, how='left', on=['project', 'stage'])
df.rename(columns={'date_x': 'begin_state', 'date_y': 'end_state'}, inplace=True)

错误输出:

projectstagebegin_stageend_stage
33New3-sep-202228-sep-2022
33Preparation11-sep-202223-sep-2022

解决方案

核心思路是识别连续的阶段分组,通过标记阶段变化的位置生成分组ID,再按分组ID聚合统计起止日期。

步骤1:转换日期格式并排序

先将date列转为datetime类型,确保时间顺序正确:

import pandas as pd

# 构造示例数据
data = [
    [33, 'New', '3-sep-2022'],
    [33, 'New', '10-sep-2022'],
    [33, 'Preparation', '11-sep-2022'],
    [33, 'Preparation', '21-sep-2022'],
    [33, 'Preparation', '23-sep-2022'],
    [33, 'New', '24-sep-2022'],
    [33, 'New', '28-sep-2022']
]
df = pd.DataFrame(data, columns=['project', 'stage', 'date'])

# 转换日期格式
df['date'] = pd.to_datetime(df['date'], format='%d-%b-%Y')
# 按项目和日期排序
df = df.sort_values(['project', 'date'])

步骤2:生成连续阶段的分组ID

通过对比当前行与上一行的stage是否一致,标记阶段变化点,再按项目累加生成唯一分组ID:

# 标记阶段变化的行
df['stage_change'] = df['stage'] != df['stage'].shift(1)
# 生成连续阶段的分组ID
df['group_id'] = df.groupby('project')['stage_change'].cumsum()

步骤3:聚合统计起止日期

按project、stage和group_id分组,提取每个组的最小(开始日期)和最大(结束日期)值,最后格式化日期并清理无关列:

# 聚合统计
result = df.groupby(['project', 'stage', 'group_id'], as_index=False).agg(
    begin_stage=('date', 'min'),
    end_stage=('date', 'max')
)

# 格式化日期为原始格式
result['begin_stage'] = result['begin_stage'].dt.strftime('%d-%b-%Y').str.lower()
result['end_stage'] = result['end_stage'].dt.strftime('%d-%b-%Y').str.lower()
# 移除分组ID列
result = result.drop('group_id', axis=1)

print(result)

最终输出

project       stage begin_stage  end_stage
0       33         New   03-sep-2022 10-sep-2022
1       33 Preparation   11-sep-2022 23-sep-2022
2       33         New   24-sep-2022 28-sep-2022

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:10:37