Skip to content

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

运行仪表盘

# 启动 Streamlit 应用
streamlit run dashboard/app.py

# 浏览器访问
# http://localhost:8501

命令行运行

# 完整流程 (数据处理→预测→库存策略→模拟)
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/ 预测结果和策略输出

🔗 相关资源


📚 理论基础

需求预测方法

方法 适用场景 优点
移动平均 稳定需求 简单、平滑噪声
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. 实时仪表盘

- 自动数据更新
- 实时预警 (库存低于 ROP)
- 移动端适配

本地路径: /workspace/code-examples/Cafe-Demand-Forecasting-Reorder-Simulator/
创建时间: 2026-06-01
难度: ⭐⭐⭐ (中级实战项目)


**Cafe-Demand-Forecasting 中文导航 | 需求预测 + 库存优化实战** [返回代码索引](../../README_UPDATED.md) | [决策科学资源大全](../../docs/resources/decision-science-comprehensive-resources.md)