尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
商超蔬菜价格弹性与补货策略:Python数据清洗到报童模型实战
简介针对某商超蔬菜价格与补货策略的建模分析压缩包适合数学建模参赛者、数据分析师及商超运营人员可用于赛题复现、业务复盘或教学参考。资源围绕数据采集清洗、时间序列预测、回归定价、库存优化等展开内含源码、数据集、可视化图表和论文模板可复现从数据预处理到策略输出的完整流程。包体共94个文件约11.59MB核心为22个xlsx数据表、6个ipynb分析笔记、2个Python脚本及2份md说明另有59张png结果图与tex/cls论文排版模板目录划分清晰便于按问题定位。已有240人浏览学习。通过阅读src脚本与notebooks交互文档可掌握Prophet销量预测、成本加成定价、排队论调度等模型的落地写法同时附带的多个品类相关性、利润率和批发价预测结果表能为复盘论文图表和进一步拓展实验提供直接参考。1. 商超蔬菜价格与补货策略研究别人给你源码和数据你该怎么落地拿到一个名为某商超蔬菜价格和补货策略研究内含源码和数据集.zip的压缩包第一反应不该是双击解压然后跑 main.py。这类项目在生鲜零售里属于典型的需求预测 价格弹性 库存优化三合一问题源码只是最后 10% 的工程量前面 90% 的时间花在数据清洗、特征构造和参数标定上。这篇文章按一个数据工程师拿到这个 zip 后的完整路径来讲先立清楚价格弹性和补货模型各自的适用范围再给能直接改参数跑的 Python 代码最后拆解源码里最容易出问题的几个环节。适合刚接触零售数据分析或准备做生鲜类项目的开发者也适合想从 Excel 转向 Python 做决策支持的运营同学。2. 数据集预处理商超蔬菜流水账怎么变成训练样本2.1 先看字段别急着画分布图商超蔬菜数据集的字段再乱也绕不开这几类SKU 编码、销售日期、销量公斤或把、零售价元/公斤、批发进价、促销标记0/1、当日到货量、报损量。有些数据集会附带天气和节假日没有的就得自己想办法补。某商超蔬菜价格和补货策略研究既然配套了数据集第一步就是做字段字典确定哪些是外生变量、哪些是决策变量。常见做法是写一个 Python 脚本把 CSV 的结构和类型打印出来同时做一次完整性的 CRC 校验防止解压时数据损坏——压缩包传输过程中出现半个字节的丢失后面所有回归结果都会变得不可信。字段名类型常见问题处理建议skustr编码不统一统一转大写去空格datestr/datetime格式混杂统一为 YYYY-MM-DDsalesfloat出现负值分退货与报损分别处理pricefloat相邻日跳变超 30%用 7 日中位数回填promoint0/1 标记缺失缺失按 0 处理别填充arrivalfloat与销量匹配不上保留原值单独建列import pandas as pd df pd.read_csv(vegetable_sales.csv, encodingutf-8) print(df.shape) print(df.dtypes) print(df.isnull().sum()) # CRC 校验下载完整性 import zlib with open(vegetable_sales.csv, rb) as f: data f.read() print(hex(zlib.crc32(data)))这段代码做两件事第一遍扫描数据集的形状和缺失情况第二遍用 zlib 的 crc32 计算文件校验值。CRC 校验在数据集下载场景里很实用尤其是从网盘或邮件附件拿到的 zip解压工具报error read zip archive或提示找不到 EOCD 记录时多半是文件没传输完整重新下载比修复快得多不需要绕到压缩包密码破解工具那一步。2.2 销量负值和价格跳变是常态生鲜销售流水表里销量出现负值通常不是数据错误而是退货、报损或盘点差异。直接删掉会损失信息全保留又会污染模型。处理逻辑一般是销量为负且绝对值小于当日正销量 5% 的视为退货运差按 0 处理超过 5% 的标记为报损事件单独建列。价格跳变则要区分是真实调价还是录入错误——同一 SKU 相邻两天零售价变动超过 30%基本可以判定为录入问题用前后 7 天中位数回填。df[sales_clean] df[sales].where(df[sales] 0, 0) daily df.groupby([sku, date])[sales_clean].sum() report_loss df[df[sales] 0].groupby([sku, date])[sales].abs() df[is_loss_event] df[sales] 0 # 价格跳变修正变动超过 30% 用 7 日中位数回填 price_delta df[price].pct_change() df.loc[price_delta.abs() 0.3, price] ( df[price].rolling(7, centerTrue).median() )参数说明销量负值的 5% 阈值和价格跳变的 30% 阈值是生鲜行业的经验值不是固定真理。叶菜类价格波动本来就大30% 可能会误伤真实调价根茎类价格稳定可以收紧到 15%。先跑分布统计再定阈值比拍脑袋可靠。注意rolling(7, centerTrue)用了中心窗口意味着回填时会用到后 3 天的数据在离线分析场景没问题如果要做线上实时预处理得改成rolling(7)并手动对齐。2.3 特征工程把日期变成模型能消化的信号蔬菜销售和天气、节气、节假日强相关。数据集里如果没有这些字段用 Python 的第三方库去补工作日、周末、农历节气、当地最高低温、降雨量每一样都要做滞后特征。补货决策真正依赖的不是今天下雨而是去年同期下雨时销量涨了多少所以特征要落在平移和比率上。df[weekday] pd.to_datetime(df[date]).dt.weekday df[is_weekend] df[weekday] 5 df[holiday] df[date].isin(holiday_list) # 滞后7天销量均值捕捉周期 df[sales_lag7] df.groupby(sku)[sales_clean].transform( lambda x: x.shift(7).rolling(7).mean() ) # 价格比当日价格 / 前7天均价 df[price_ratio] df[price] / df.groupby(sku)[price].transform( lambda x: x.shift(1).rolling(7).mean() )这里的关键参数是滞后窗口选 7 而不是 3。生鲜蔬菜存在明显的周周期周末销量高峰、周中低谷7 天滞后能平滑掉单日噪音。价格比这个特征是把绝对价格转换成相对价格方便后面做价格弹性分析时排除整体物价上涨的影响。免费 Python 源码大全里常见的是直接用日期做 one-hot那样会制造出几十个稀疏列对树模型不友好对回归更是灾难。3. 价格弹性分析找到涨价多少会少卖多少的量化答案3.1 模型选型为什么用对数线性而不是线性回归商超定价的核心问题是价格弹性系数——价格上涨 1%销量下降百分之几。对蔬菜这种需求价格弹性不恒定的商品线性模型假设弹性固定在低价区间会高估销量、高价区间会低估所以主流做法是对销量和价格同时取对数做对数线性回归。弹性系数就是这个模型里价格的回归系数。这个项目的源码里如果用的是普通线性回归跑价格系数第一件事就是把它改成 OLS-log 模型。import statsmodels.api as sm import numpy as np df[log_sales] np.log(df[sales_clean] 1) df[log_price] np.log(df[price]) df[log_lag7] np.log(df[sales_lag7] 1) X df[[log_price, log_lag7, holiday, is_weekend]] X sm.add_constant(X) model sm.OLS(df[log_sales], X).fit() print(model.summary())逻辑说明对销量加 1 再取对数是为了避免销量为 0 时出现负无穷log_lag7放进模型是为了控制销量惯性如果不控制它价格系数的绝对值会被高估。运行 summary 后需要看三列coef是弹性系数p 值要小于 0.05R-squared 在这个场景下到 0.4 以上就是可用的——时间序列横截面混合数据很难跑出很高的 R²别追求教材里的 0.9。3.2 分组跑弹性叶菜和根茎是两个物种把全部 SKU 放一起算一个弹性系数是整个分析里最容易出错的操作。菠菜、油菜这类叶菜保鲜期短、替代品多价格弹性系数通常在 -1.5 到 -2.5 之间涨一点价销量就明显下滑土豆、胡萝卜这类根茎耐储存、刚需属性强弹性大概率在 -0.3 到 -0.6 之间。合并建模会把两组商品的平均效应算出来导致每个 SKU 的定价建议都是错的。results {} for category in df[category].unique(): sub df[df[category] category].copy() sub[log_sales] np.log(sub[sales_clean] 1) sub[log_price] np.log(sub[price]) X sm.add_constant(sub[[log_price, holiday, is_weekend]]) model sm.OLS(sub[log_sales], X).fit() results[category] model.params[log_price] print(results)按品类分组跑完之后每个类别会得到一个弹性系数表。这个表的直接用途是定价决策弹性绝对值大于 1 的商品降价促销能带来销售额增长小于 1 的降价只会压毛利。商超蔬菜的定价策略基本就是高弹性单品用低价引流低弹性单品做毛利担当。这个结论反过来会指导补货模型里的单品分层所以分组弹性计算要跑在补货策略之前。3.3 促销变量必须单独建模数据集里有促销标记的不要把它并进价格变量里。蔬菜促销往往是每斤减两元而不是打八折如果直接用零售价做变量促销期间的销量抬升会被误判成低价敏感弹性系数会虚高。处理办法是加一个促销虚拟变量同时把价格拆成常规价和促销价两个字段。源码里如果只有一个 price 列跑出来的弹性系数大概率偏大要对这份源码的输出保持怀疑这一条能省下后面很多无效调参的时间。4. 补货策略实战报童模型在蔬菜订货上的落地写法4.1 报童模型为什么适合生鲜补货决策的本质是多订了怕损耗少订了怕缺货的权衡。报童模型Newsvendor Model正好解决这个问题它把最优订货量定义为边际成本等于边际收益的点多进一份货能卖出去赚的毛利和卖不出去亏的进价两者相等时的订货量就是最优值。蔬菜和报纸的高度相似在于都是当日损耗、当日报损今天卖不掉明天基本不能卖。源码里如果补货部分用的是简单移动平均预测可以在这个基础上叠加报童模型来修正订货量。import scipy.stats as st import numpy as np # 参数毛利率、损耗率、服务水平 gross_margin 0.35 cost 3.2 price 4.9 unit_profit price - cost unit_loss cost # 服务水平 单位收益 / (单位收益 单位损失) service_level unit_profit / (unit_profit unit_loss) # 用历史销量的均值和标准差近似需求分布 forecast_mean 150 forecast_std 30 z st.norm.ppf(service_level) optimal_qty forecast_mean z * forecast_std print(f服务水平: {service_level:.3f}, 最优补货量: {optimal_qty:.0f})逻辑说明service_level就是报童模型的最优缺货概率它由毛利率结构决定。毛利率越高缺货的机会成本越大服务水平就越高订货量越偏向多进毛利率低、损耗率高的商品服务水平就低订货量保守。forecast_mean和forecast_std来自历史销量预测实际项目中用上一节加的滞后特征去拟合每日均值再算残差的标准差不要直接拿原始销量算。gross_margin在这里只用来理解服务水平的形成订货量计算本身不需要它真正决定订货量的是均值和标准差的估计质量。4.2 预测和补货为什么要分离一个常见的错误是把预测模型和补货模型揉在一起用一个神经网络直接输出订货量。高频小幅度的日常补货不建议这么干生鲜数据量小、噪音大黑盒模型的误差难定位。工程上建议保持预测 决策两段式先预测需求分布均值加方差再用报童模型把分布转成订货量。这样当天预测偏了能分清是预测的锅还是订货量计算的问题。# 两段式实现预测均值/方差 - 报童订货量 from statsmodels.tsa.holtwinters import ExponentialSmoothing model ExponentialSmoothing( series, seasonal_periods7, trendadd, seasonaladd ).fit() mean_forecast model.forecast(1)[0] residuals model.resid std_forecast residuals.std() def newsvendor_qty(mean, std, profit, loss): sl profit / (profit loss) z st.norm.ppf(sl) return max(0, mean z * std)参数说明Holt-Winters 的三次指数平滑在这里比 ARIMA 更实用因为生鲜需求有明确的一周季节性而且对短期预测来说指数平滑的延迟特性反而是优点。seasonal_periods7固定了周周期trendadd表示允许销量缓慢增长。残差的标准差作为需求波动估计这一步决定了安全库存的大小波动估计偏小会导致缺货率飙升。newsvendor_qty里对最终结果做了max(0, ...)截断防止负订货量。4.3 安全库存不是拍脑袋的多进 10%很多运营习惯用预测值乘以 1.1来做安全库存这在生鲜品类是有问题的。10% 的加量在需求波动大的叶菜上远远不够在土豆这种耐储商品上又造成库存积压。安全库存的正确计算方式是 z 值乘以需求标准差再乘以补货周期 lead time 的平方根。每天凌晨配送到店的商品lead time 接近 0安全库存可以很小但如果仓库要隔天到货lead time 变成 1安全库存就要乘以 1.41。lead_time_days 1 safety_stock st.norm.ppf(0.95) * std_forecast * np.sqrt(lead_time_days) order_qty max(0, round(mean_forecast safety_stock - stock_on_hand))注意这个公式算的是今天该订多少不是今天该到多少。如果日清模式已经包含在 lead_time 里stock_on_hand就是当日开门前的可用库存。95% 的服务水平对应 z 值约 1.65换算成缺货率是 5%商超通常取 90% 到 95% 之间高了损耗受不了低了顾客抱怨。最终参数取多少要用历史数据回测一张表格来定不能凭感觉。服务水平z 值适用场景预期缺货率85%1.04低毛利、高损耗叶菜15%90%1.28常规蔬菜10%95%1.65高毛利、引流单品5%97%1.88招牌菜、会员单品3%5. 拿到 zip 后的验证清单和参数敏感性调试5.1 解压后不要急着跑先做三件事第一件事是校验压缩包完整性用unzip -t在 Linux 上测试Windows 下用 7-Zip 的测试按钮。如果报错指向 EOCD 缺失或 read zip archive 失败多半是 zip 没有传输完整这类问题跟压缩包密码无关直接重新下载就行。第二件事是检查依赖版本运行pipreqs或直接看 requirements.txt 里的 numpy、pandas、statsmodels 版本statsmodels 在不同版本之间的 API 差异很大sm.add_constant和结果对象的字段名都变过。第三件事是把数据集拆成训练集和验证集按时间切分而不是随机切分——生鲜数据有强时序性随机抽样会让模型偷偷看到未来信息回测结果虚高。unzip -t 某商超蔬菜价格和补货策略研究内含源码和数据集.zip python -m pipreqs . --force5.2 用滚动回测调服务水平和弹性分组import pandas as pd import numpy as np def backtest(service_level, df): total_profit 0 total_spoilage 0 total_shortage 0 for date, day_data in df.groupby(date): # 模拟当日订货与销售 order predict_and_order(day_data, service_level) sales day_data[sales_clean].sum() arranged min(order, sales) shortage max(0, sales - order) spoilage max(0, order - sales) * 0.5 # 部分可退货 total_profit arranged * unit_profit - spoilage * unit_loss return total_profit for sl in [0.85, 0.90, 0.95]: profit backtest(sl, df) print(f服务水平 {sl:.0%} 时回测毛利 {profit:.0f})回测输出的几组数字放在一起看才有意义毛利、损耗量和缺货次数。服务水平从 0.90 调到 0.95毛利可能只增加 3%损耗却涨了 15%那就不值得提服务水平。这个权衡没有标准答案取决于门店对缺货的口碑敏感度。调参的时候顺带把弹性分析里的分组结果当成先验信息高弹性组用低服务水平保毛利低弹性组用高服务水平保口碑。源码里的注释和数据集字段名可以当参考但模型结构建议按自己的数据质量重写。生鲜补货的坑大多不在算法而在数据价格跳变、销量负值、促销混淆这三个问题处理干净报童模型和弹性分析的结果就基本可信了。把跑通的参数组合沉淀成一个 JSON 配置文件每次调完价格或换季时直接改配置比改代码快得多也方便不同门店直接复制同一套策略。本文还有配套的精品资源点击获取
RELATED

相关推荐

Vibe-Trading 行为金融技能:过反应与无反应、情绪周期与去偏差的定量化实战指南

Vibe-Trading 行为金融技能:过反应与无反应、情绪周期与去偏差的定量化实战指南

Vibe-Trading 行为金融技能:过反应与无反应、情绪周期与去偏差的定量化实战指南 【免费下载链接】Vibe-Trading "Vibe-Trading: Your Personal Trading Agent" 项目地址: https://gitcode.com/GitHub_Trending/vi/Vibe-Trading 本文以 Vibe-Tradin…

📅 2026/9/10 14:45:52
Hallmark 反模式清单(Anti-Patterns):如何按名识别并修复 AI 生成界面的 43 个“指纹“

Hallmark 反模式清单(Anti-Patterns):如何按名识别并修复 AI 生成界面的 43 个“指纹“

Hallmark 反模式清单(Anti-Patterns):如何按名识别并修复 AI 生成界面的 43 个"指纹" 【免费下载链接】hallmark Anti-AI-slop design skill for Claude Code, Cursor, and Codex. 项目地址: https://gitcode.com/GitHub_Trendin…

📅 2026/9/10 14:45:52
风光储并网系统Simulink仿真建模与协同控制策略

风光储并网系统Simulink仿真建模与协同控制策略

1. 项目背景与核心价值风光储并网系统作为新能源电力领域的重要研究方向,正在全球范围内获得广泛应用。这个Simulink仿真模型研究项目,聚焦于永磁同步风机、光伏阵列和储能电池组的协同运行控制,为实际工程应用提供可靠的数字仿真平台。我在电…

📅 2026/9/10 14:45:51
MORE NEWS

更多资讯

📰

临时文件自动化管理:原理、技术与实践

1. 临时文件管理痛点与自动化需求每次打开工程软件或浏览器,系统都会默默生成一堆临时文件。这些文件就像办公桌上随手堆放的便签纸——刚创建时有用,但三天后就成了碍事的垃圾。我最近帮同事清理一台卡顿的电脑时,发现C盘被23.4GB的临时文件…

📰

物流业应对90%高退货率:逆向物流优化与电商协作策略

1. 全球物流业面临"退货季"冲击 最近打开物流行业的数据报表,一组数字让我这个从业十年的老物流人都不禁倒吸一口凉气——女士连衣裙类商品的退货率已经飙升到接近90%。这意味着每10件发出的连衣裙,就有9件会原路返回仓库。这种前所未有的高退…

📰

V++语言:高性能系统编程的创新与实践

1. V语言定位与核心优势 V是一种新兴的系统级编程语言,专注于高性能计算和底层开发领域。它融合了现代语言设计理念与硬件级优化能力,在编译器技术、内存管理、并发模型等方面进行了针对性创新。与传统的C相比,V在保持相近性能的同时&#xf…

📰

oh-my-claudecode 的 ultragoal 怎么在没有活动执行循环时维护持久化目标账本?

oh-my-claudecode 的 ultragoal 怎么在没有活动执行循环时维护持久化目标账本? 【免费下载链接】oh-my-claudecode Teams-first Multi-agent orchestration for Claude Code 项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-claudecode 在 oh-my-cl…

📰

实时行情系统架构设计:协议选型、数据源与高可用实战

做行情系统这行久了,最常被问的一句话就是:"你们那实时行情到底有多实时?"这个问题听起来简单,背后牵出来的链路却很长:从交易所或数据源发出第一笔行情,到用户屏幕上那个数字跳动,中…

📰

rclone WebDAV 后端全解析:从交互式配置到供应商差异与协议级实现

rclone WebDAV 后端全解析:从交互式配置到供应商差异与协议级实现 【免费下载链接】rclone "rsync for cloud storage" - Google Drive, S3, Dropbox, Backblaze B2, One Drive, Swift, Hubic, Wasabi, Google Cloud Storage, Azure Blob, Azure Files, Y…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬