如何在Pandas中构建库存耗尽日期计算列
仓库补货库存耗尽日期计算问题修复
需求说明
生成DataFrame,展示仓库中每笔补货对应的库存耗尽日期(计算时需排除后续补货的影响)。
初始DataFrame构建代码
import pandas as pd data = {'warehouse': ['M1', 'M1', 'M1', 'M1', 'M1', 'M1', 'M1', 'M1', 'M1', 'M2'], 'item': ['Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partxy', 'Partz'], 'date': ['01/01/2023', '05/01/2023', '07/01/2023', '08/01/2023', '09/01/2023', '10/01/2023', '15/01/2023', '18/01/2023', '19/01/2023', '22/01/2023'], 'tot_load_replenishment': [0, 0, 20, 0, 0, 50, 0, 50, 0, 0], 'tot_unload': [0, -30, -15, -50, -10, -5, -30, -10, -5, -10], 'stock': [100, 70, 75, 25, 15, 60, 30, 70, 65, 300], 'stock_before_load': [None, None, 55, None, None, 10, None, 20, None, None]} load_unload = pd.DataFrame(data) load_unload['tot_load_replenishment'] = load_unload['tot_load_replenishment'].astype(int) load_unload['tot_unload'] = load_unload['tot_unload'].astype(int) load_unload['date'] = pd.to_datetime(load_unload['date'], format='%d/%m/%Y').dt.strftime('%Y-%m-%d')
原代码问题分析
原代码核心错误有两点:
- 未排除后续补货的干扰:后续补货会打断当前库存的消耗周期,计算时需限定在当前补货到下一次补货的时间范围内。
- 库存耗尽判断逻辑错误:用单条出库记录直接和剩余库存比较,应该用累计出库量判断是否超过补货前的剩余库存。
修复后的代码
# 筛选目标仓库和物料 item = 'Partxy' warehouse = 'M1' item_war_mask = (load_unload['item'] == item) & (load_unload['warehouse'] == warehouse) load_unload_item_war = load_unload[item_war_mask].copy() # 转换日期为datetime类型,方便时间比较 load_unload_item_war['date'] = pd.to_datetime(load_unload_item_war['date']) # 获取所有补货记录 mov_replenishment = load_unload_item_war[load_unload_item_war['tot_load_replenishment'] > 0].copy() # 提取所有补货日期,用于划分每个补货的消耗周期 replenish_dates = mov_replenishment['date'].tolist() def get_exhaustion_date(row, df, replenish_dates): current_replenish_date = row['date'] residual_stock = row['stock_before_load'] # 找到下一次补货日期,作为当前消耗周期的截止点 next_replenish_dates = [d for d in replenish_dates if d > current_replenish_date] end_date = next_replenish_dates[0] if next_replenish_dates else pd.Timestamp.max # 筛选当前补货后、下一次补货前的出库记录 period_df = df[(df['date'] > current_replenish_date) & (df['date'] < end_date)].copy() # 计算累计出库量(转为正数便于比较) period_df['cumulative_unload'] = period_df['tot_unload'].abs().cumsum() # 找到第一个累计出库量超过剩余库存的日期 exhausted_mask = period_df['cumulative_unload'] > residual_stock if exhausted_mask.any(): return period_df[exhausted_mask]['date'].min().strftime('%Y-%m-%d') else: # 周期内库存未耗尽则返回None return None # 应用函数计算每笔补货的耗尽日期 mov_replenishment['exhaustion_date'] = mov_replenishment.apply( lambda row: get_exhaustion_date(row, load_unload_item_war, replenish_dates), axis=1 ) # 输出结果 print(mov_replenishment[['warehouse', 'item', 'date', 'tot_load_replenishment', 'stock_before_load', 'exhaustion_date']])
代码说明
- 日期类型转换:将日期转为
datetime类型,避免字符串比较的潜在误差。 - 补货周期划分:为每笔补货匹配下一次补货日期,限定当前库存消耗的时间范围,彻底排除后续补货的干扰。
- 累计出库判断:通过计算周期内累计出库量,精准定位库存耗尽的第一个日期。
- 边界处理:如果当前补货周期内库存未耗尽(到下一次补货仍有剩余),返回
None标记。
内容的提问来源于stack exchange,提问作者finoz
相关产品推荐
相关产品推荐

