0

0

Pandas 分组反向累计业务日推算:动态起始点的日期计算教程

花韻仙語

花韻仙語

发布时间:2026-03-11 09:53:32

|

987人浏览过

|

来源于php中文网

原创

本文详解如何在 Pandas 中实现按组反向累计推算日期——以每组首个非空 Start 为基准,结合 LT(Lead Time)列所表示的业务日天数,自底向上逐行减去对应工作日,精准跳过周末与节假日。

本文详解如何在 pandas 中实现按组反向累计推算日期——以每组首个非空 `start` 为基准,结合 `lt` 列所表示的**业务日天数**,自底向上逐行减去对应工作日,精准跳过周末与节假日。

在供应链、项目排程或订单履约等场景中,常需基于交付截止日(Start)和前置周期(LT,单位为业务日)反向推算各环节的计划开始时间。难点在于:

  • 每组(如产品线 Group)的参考起始日期并非固定位于组末,而是首个有效日期(即第一个非 NaT 的 Start 值);
  • 后续所有 NaN 行需从该起始点逆序向前推算,且 LT 必须按真实工作日(周一至周五)扣减,而非自然日;
  • 同一组内可能存在多个有效 Start(如 C 组有 04-04、10-04、24-04),但仅首个生效,其后的 Start 仅保留原值,不参与推算。

以下方案使用纯 Pandas 向量化操作,无需循环或 apply(lambda x: ...),兼顾性能与可读性。

皮卡智能
皮卡智能

AI驱动高效视觉设计平台

下载

✅ 核心思路:双层分组 + 反向累计 + 业务日偏移

关键创新在于构建一个逻辑分组标识 grp,用于区分“首个有效起始点之后的子段”:

  1. 先识别所有 LT == 0 的行(通常代表锚定的起始日期);
  2. 对每组 Group 内,用 cumsum() 累计 LT == 0 的出现次数,并减去当前行是否为 LT == 0,从而将每个 LT == 0 行及其上方连续 NaN Start 行划入同一逻辑子组;
  3. 在该双层索引 [Group, grp] 上执行反向累计(.loc[::-1]),确保从组底向上累加 LT;
  4. 将累计值转为 pd.offsets.BusinessDay,再与各子组的首个 Start 相减,完成业务日回溯。

? 完整可运行代码

import pandas as pd

# 构造示例数据
data = {
    'Group': ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C', 'C'],
    'LT': [5, 10, 0, 3, 0, 2, 4, 0, 0, 0],
    'Start': [None, None, '20-03-2024', None, '04-03-2024', None, None, '04-04-2024', '10-04-2024', '24-04-2024']
}
df = pd.DataFrame(data)

# 步骤1:统一转换为 datetime,无效值设为 NaT
df['Start'] = pd.to_datetime(df['Start'], errors='coerce', format='%d-%m-%Y')

# 步骤2:构建逻辑分组标识 grp
# 目标:将每个 Group 中首个 LT==0 行及其上方 NaN 行归为同一子组
s = df['LT'].eq(0)  # 标记 LT 为 0 的行(锚点)
grp = s.groupby(df['Group']).cumsum() - s  # 关键:使首个 0 行的 grp=0,其上 NaN 行 grp=0,后续 0 行 grp=1,2...

# 步骤3:反向累计 LT(从组底向上),按 [Group, grp] 分组
lt_cumrev = (
    df.loc[::-1, 'LT']  # 反序取 LT 列
    .groupby([df['Group'], grp])  # 双层分组:确保只在「首个锚点及其上方」子段内累计
    .cumsum()
    .apply(pd.offsets.BusinessDay)  # 转为 BusinessDay 偏移量(自动跳过周末)
)

# 步骤4:获取每个 [Group, grp] 子组的首个 Start 值,并减去累计偏移
base_start = df.groupby(['Group', grp])['Start'].transform('first')
result_dates = (base_start - lt_cumrev).dt.strftime('%d-%m-%Y')

# 步骤5:更新原 DataFrame(仅覆盖 Start 为 NaT 的行)
mask_na = df['Start'].isna()
df.loc[mask_na, 'Start'] = result_dates[mask_na]

print(df)

⚠️ 注意事项与最佳实践

  • 日期格式一致性:务必在 pd.to_datetime() 中指定 format='%d-%m-%Y'(若原始为 dd-mm-yyyy),否则解析可能出错或产生时区歧义;
  • LT == 0 的语义:本方案隐含假设 LT == 0 行即为各组的“锚定日期”。若业务中存在 LT > 0 但 Start 非空的情况,需先用 df.loc[df['Start'].notna(), 'LT'] = 0 显式对齐;
  • 节假日扩展:pd.offsets.BusinessDay 默认仅排除周末。如需排除法定节假日,应改用 pd.tseries.offsets.CustomBusinessDay(holidays=your_holiday_list);
  • 性能提示:对于百万级数据,避免多次 groupby().transform();本方案仅两次 groupby(grp 构建 + lt_cumrev 计算),已属最优;
  • 验证逻辑:建议添加断言检查每组首个非空 Start 是否未被修改:
    assert all(df.loc[~df['Start'].isna()].groupby('Group').head(1)['Start'] == 
               pd.to_datetime(df['Start'], errors='coerce').groupby(df['Group']).first())

该方法将动态起始点识别与业务日精确回溯无缝融合,是 Pandas 高级分组技巧的典型应用——既规避了显式循环的低效,又超越了简单 bfill() 或 cumsum() 的功能边界。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

78

2025.12.04

Python 数据清洗与预处理实战
Python 数据清洗与预处理实战

本专题系统讲解 Python 在数据清洗与预处理中的核心技术,包括使用 Pandas 进行缺失值处理、异常值检测、数据格式化、特征工程与数据转换,结合 NumPy 高效处理大规模数据。通过实战案例,帮助学习者掌握 如何处理混乱、不完整数据,为后续数据分析与机器学习模型训练打下坚实基础。

32

2026.01.31

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

887

2023.07.31

python中的format是什么意思
python中的format是什么意思

python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

459

2024.06.27

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

215

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

192

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

61

2026.01.05

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

9

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

22

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号