如何构建库存盘点排程Python脚本?求思路指引
思路指引(贴合Pandas使用习惯)
1. 先统一日期格式,打好基础
- 把
Deadline和Proposed列转成datetime类型,方便后续日期比较、偏移计算:df[['Deadline', 'Proposed']] = df[['Deadline', 'Proposed']].apply(pd.to_datetime, format='%d %b') - 提前生成合法日期池:把所有符合「非周末、非冻结期」的日期整理成有序列表,后续调整日期时直接从池子里取,避免重复判断合法性。
2. 处理「同一区域内地点不同天」约束
基于你已有的初始Proposed日期,按区域分组处理:
- 按
Area分组,给每个区域维护一个已使用日期的集合 - 遍历区域内的每个地点,若当前
Proposed日期已被同区域占用,就从合法日期池里找该地点截止日期之前、晚于当前日期的下一个合法日期,直到找到未被同区域占用的日期 - 核心伪代码:
for area, group in df.groupby('Area'): used_dates = set() for idx, row in group.iterrows(): current_date = row['Proposed'] # 循环找符合条件的日期 while current_date in used_dates or current_date >= row['Deadline']: # 从合法日期池取下一个更大的日期 current_date = next(d for d in valid_dates if d > current_date) df.loc[idx, 'Proposed'] = current_date used_dates.add(current_date)
3. 处理「同一日期盘点次数不超过n次」约束
完成区域约束调整后,再处理每日次数限制:
- 先统计每日盘点次数:
daily_counts = df['Proposed'].value_counts() - 针对次数超标的日期,优先调整截止日期较晚的地点(给调整留更多空间),从合法日期池里找满足以下条件的候选日期:
- 早于该地点的截止日期
- 未被该地点所属区域占用
- 候选日期的当前盘点次数 <n
- 核心伪代码:
n = 2 # 替换为你的阈值 # 循环直到所有日期的计数都符合要求 while (df['Proposed'].value_counts() > n).any(): over_dates = df['Proposed'].value_counts()[lambda x: x > n].index for date in over_dates: # 优先调整截止日期晚的行 rows_to_adjust = df[df['Proposed'] == date].sort_values('Deadline', ascending=False) for idx, row in rows_to_adjust.iterrows(): if df['Proposed'].value_counts()[date] <= n: break current_date = row['Proposed'] # 遍历合法日期池找候选 for candidate in valid_dates: area_used_dates = df[df['Area'] == row['Area']]['Proposed'].values if (candidate > current_date and candidate < row['Deadline'] and candidate not in area_used_dates and df['Proposed'].value_counts().get(candidate, 0) < n): df.loc[idx, 'Proposed'] = candidate break
4. 优化建议
- 用
bisect模块对有序的合法日期池做二分查找,替代遍历,提升大数据量下的调整效率 - 可以把「合法日期池」按截止日期分段,进一步缩小候选日期的查找范围
内容的提问来源于stack exchange,提问作者Krystof Meier
相关产品推荐
相关产品推荐

