Cafe-Demand-Forecasting 中文导航¶
原文: Café Demand Forecasting + Inventory Reorder Simulator
分类: 需求预测 + 库存优化
大小: 1.5 MB
语言: Python + Streamlit
📚 项目简介¶
Cafe-Demand-Forecasting 是一个咖啡馆需求预测和库存重订货模拟器项目。它将交易数据转换为: 1. 单品级别的日需求预测 2. 库存重订货策略 (Reorder Point + Safety Stock) 3. 蒙特卡洛缺货风险模拟
GitHub: https://github.com/decision-science/Cafe-Demand-Forecasting-Reorder-Simulator
🔧 核心功能¶
| 功能 | 说明 | 技术 |
|---|---|---|
| 数据清洗 | 交易级→日级聚合,零填充缺失天数 | pandas |
| 需求预测 | 多种基线模型回测,按单品选择最优 | 移动平均/EWMA/季节性朴素 |
| 库存策略 | 安全库存、重订货点 (ROP)、订货上限 (S) | 统计方法 |
| 风险模拟 | 蒙特卡洛模拟缺货风险 | NumPy |
| 可视化仪表盘 | Streamlit 交互式仪表盘 | Streamlit + Plotly |
📁 目录结构¶
Cafe-Demand-Forecasting-Reorder-Simulator/
├── data/ # 数据目录
│ ├── raw/ # 原始交易数据
│ └── processed/ # 处理后的日需求数据
├── src/ # 源代码
│ ├── data_processing/ # 数据处理
│ │ ├── clean.py
│ │ └── aggregate.py
│ ├── forecasting/ # 预测模型
│ │ ├── baselines.py
│ │ └── backtest.py
│ ├── inventory/ # 库存策略
│ │ ├── rop.py
│ │ └── safety_stock.py
│ └── simulation/ # 蒙特卡洛模拟
│ └── risk.py
├── dashboard/ # Streamlit 仪表盘
│ └── app.py
├── notebooks/ # Jupyter 分析笔记
├── outputs/ # 输出结果
│ ├── forecasts/
│ ├── policies/
│ └── visualizations/
├── requirements.txt # 依赖
└── README.md # 主文档
🚀 快速开始¶
安装¶
# 克隆仓库
cd /workspace/code-examples/Cafe-Demand-Forecasting-Reorder-Simulator
# 安装依赖
pip install -r requirements.txt
# 主要依赖:
# - pandas, numpy
# - scikit-learn
# - streamlit, plotly
# - matplotlib, seaborn
运行仪表盘¶
命令行运行¶
# 完整流程 (数据处理→预测→库存策略→模拟)
python main.py --data data/raw/transactions.csv
# 仅运行预测
python main.py --step forecast
# 仅运行库存策略
python main.py --step inventory
# 仅运行风险模拟
python main.py --step simulation
📊 仪表盘导览¶
A) 概览标签页 (健康检查 + 优先级)¶
展示内容: - 数据覆盖: 天数/单品数/总收入 - 单品收入排名: 识别最重要的单品 - 预测模型回测对比: 比较不同基线模型表现
为什么重要:
"数据集是否有效?哪些单品值得重点关注?哪种预测方法整体表现最佳?"
B) 单品探索标签页 (历史 + 预测)¶
展示内容:
- 历史日需求: 原始需求行为 (包括波动和异常)
- 历史 + 预测:
- history 线 = 观测需求
- forecast 线 = 下一周期基线预测
如何解读: - 稳定需求 → 移动平均/EWMA 表现好 - 周模式需求 (周末/工作日差异) → 季节性朴素方法胜出 - 大幅波动 → 需询问运营:促销?团购?数据录入错误?
C) 库存策略标签页 (ROP 表 + 风险 + 单品解释)¶
策略表字段: | 字段 | 说明 | |------|------| | μ (mu) | 平均日需求 (件/天) | | σ (sigma) | 需求波动标准差 | | 服务水平 | 目标不缺货概率 | | z | 服务水平对应的 z 分数 | | 提前期 (天) | 供应商交货时间 | | 安全库存 | 应对波动的缓冲库存 | | ROP | 库存低于此值时重订货 | | 订货上限 (S) | 订货后目标库存水平 |
模拟结果表: | 指标 | 说明 | |------|------| | avg_stockout_day_rate | 缺货天数比例 (%) | | avg_onhand_units | 平均手持库存 | | avg_unmet_demand_units | 未满足需求 (销售损失代理) |
💡 核心方法¶
1. 数据清洗流程¶
# 交易级数据 → 日级需求
import pandas as pd
# 读取原始交易数据
df = pd.read_csv('transactions.csv')
# 按日期 + 单品聚合
daily_demand = df.groupby(['date', 'item'])['quantity'].sum().reset_index()
# 零填充缺失天数 (创建连续时间序列)
daily_demand = daily_demand.pivot(index='date', columns='item', values='quantity')
daily_demand = daily_demand.reindex(
pd.date_range(start=daily_demand.index.min(),
end=daily_demand.index.max(),
freq='D'),
fill_value=0
)
2. 预测基线模型¶
# 移动平均 (Moving Average)
def moving_average_forecast(series, window=7):
return series.rolling(window=window).mean().iloc[-1]
# 指数加权移动平均 (EWMA)
def ewma_forecast(series, alpha=0.3):
return series.ewm(alpha=alpha).mean().iloc[-1]
# 季节性朴素 (Seasonal Naive)
def seasonal_naive_forecast(series, period=7):
return series.iloc[-period]
3. 库存策略计算¶
import numpy as np
from scipy.stats import norm
def calculate_rop(mu_daily, sigma_daily, lead_time, service_level):
"""
计算重订货点 (ROP) 和安全库存
参数:
- mu_daily: 平均日需求
- sigma_daily: 日需求标准差
- lead_time: 提前期 (天)
- service_level: 服务水平 (如 0.95)
"""
# 提前期需求
mu_lt = mu_daily * lead_time
sigma_lt = sigma_daily * np.sqrt(lead_time)
# z 分数
z = norm.ppf(service_level)
# 安全库存
safety_stock = z * sigma_lt
# 重订货点
rop = mu_lt + safety_stock
# 订货上限 (Order-up-to level)
order_up_to = mu_daily * (lead_time + review_period) + safety_stock
return {
'safety_stock': safety_stock,
'rop': rop,
'order_up_to': order_up_to
}
4. 蒙特卡洛风险模拟¶
def simulate_inventory_policy(mu, sigma, rop, order_up_to, lead_time, n_days=365):
"""
模拟库存策略表现
返回:
- 缺货率
- 平均库存
- 未满足需求
"""
inventory = order_up_to
stockouts = 0
total_inventory = 0
unmet_demand = 0
for day in range(n_days):
# 模拟当日需求 (正态分布)
demand = np.random.normal(mu, sigma)
demand = max(0, demand) # 需求不能为负
# 检查是否缺货
if demand > inventory:
stockouts += 1
unmet_demand += demand - inventory
inventory = 0
else:
inventory -= demand
# 检查是否需要订货
if inventory <= rop:
# 在途库存 (lead_time 天后到货)
# 简化:假设立即补货到 order_up_to
inventory = order_up_to
total_inventory += inventory
return {
'stockout_rate': stockouts / n_days,
'avg_inventory': total_inventory / n_days,
'unmet_demand': unmet_demand
}
🎯 决策问题¶
这个项目围绕一个实际决策问题构建:
"对于每个单品,我何时应该重订货 (ROP)?应该订多少 (Order-up-to)?我接受的缺货风险是多少?"
输入¶
- 历史交易数据 (CSV)
- 提前期 (天)
- 目标服务水平 (%)
- 需求预测 horizon
输出¶
- 每个单品的 ROP 和安全库存
- 缺货风险估计
- 最优订货策略建议
📖 关键文档¶
| 文档 | 说明 |
|---|---|
README.md |
项目介绍和使用指南 |
dashboard/app.py |
Streamlit 仪表盘代码 |
notebooks/ |
Jupyter 分析笔记 |
outputs/ |
预测结果和策略输出 |
🔗 相关资源¶
- security-decision-labs - 决策科学实验平台
- decision-science-comprehensive-resources - 决策科学资源大全
📚 理论基础¶
需求预测方法¶
| 方法 | 适用场景 | 优点 |
|---|---|---|
| 移动平均 | 稳定需求 | 简单、平滑噪声 |
| EWMA | 缓慢变化需求 | 近期权重更高 |
| 季节性朴素 | 有明显周期性 | 捕捉季节模式 |
| Holt-Winters | 趋势 + 季节 | 全面但复杂 |
库存管理概念¶
| 概念 | 公式 | 说明 |
|---|---|---|
| 安全库存 | z × σ_LT | 应对不确定性 |
| ROP | μ_LT + SS | 触发订货点 |
| 服务水平 | P(不缺货) | 目标概率 |
🛠️ 扩展建议¶
1. 添加高级预测模型¶
# Prophet (Facebook)
from fbprophet import Prophet
# ARIMA
from statsmodels.tsa.arima.model import ARIMA
# XGBoost
import xgboost as xgb
2. 多级库存优化¶
3. 实时仪表盘¶
本地路径: /workspace/code-examples/Cafe-Demand-Forecasting-Reorder-Simulator/
创建时间: 2026-06-01
难度: ⭐⭐⭐ (中级实战项目)