2023年国赛高教杯数学建模
C题 蔬菜类商品的自动定价与补货决策
原题再现
在生鲜商超中,一般蔬菜类商品的保鲜期都比较短,且品相随销售时间的增加而变差,大部分品种如当日未售出,隔日就无法再售。因此,商超通常会根据各商品的历史销售和需求情况每天进行补货。
由于商超销售的蔬菜品种众多、产地不尽相同,而蔬菜的进货交易时间通常在凌晨 3:00-4:00,为此商家须在不确切知道具体单品和进货价格的情况下,做出当日各蔬菜品类的补货决策。蔬菜的定价一般采用“成本加成定价”方法,商超对运损和品相变差的商品通常进行打折销售。可靠的市场需求分析,对补货决策和定价决策尤为重要。从需求侧来看,蔬菜类商品的销售量与时间往往存在一定的关联关系;从供给侧来看,蔬菜的供应品种在 4 月至 10月较为丰富,商超销售空间的限制使得合理的销售组合变得极为重要。
附件 1 给出了某商超经销的 6 个蔬菜品类的商品信息;附件 2 和附件 3 分别给出了该商超 2020 年 7 月 1 日至 2023 年 6 月 30 日各商品的销售流水明细与批发价格的相关数据;
附件 4 给出了各商品近期的损耗率数据。请根据附件和实际情况建立数学模型解决以下问题:
问题 1 蔬菜类商品不同品类或不同单品之间可能存在一定的关联关系,请分析蔬菜各品类及单品销售量的分布规律及相互关系。
问题 2 考虑商超以品类为单位做补货计划,请分析各蔬菜品类的销售总量与成本加成定价的关系,并给出各蔬菜品类未来一周(2023 年 7 月 1-7 日)的日补货总量和定价策略,使得商超收益最大。
问题 3 因蔬菜类商品的销售空间有限,商超希望进一步制定单品的补货计划,要求可售单品总数控制在 27-33 个,且各单品订购量满足最小陈列量 2.5 千克的要求。根据 2023年 6 月 24-30 日的可售品种,给出 7 月 1 日的单品补货量和定价策略,在尽量满足市场对各品类蔬菜商品需求的前提下,使得商超收益最大。
问题 4 为了更好地制定蔬菜商品的补货和定价决策,商超还需要采集哪些相关数据,这些数据对解决上述问题有何帮助,请给出你们的意见和理由。
附件 1 6 个蔬菜品类的商品信息
附件 2 销售流水明细数据
附件 3 蔬菜类商品的批发价格
附件 4 蔬菜类商品的近期损耗率
注 (1) 附件 1 中,部分单品名称包含的数字编号表示不同的供应来源。
(2) 附件 4 中的损耗率反映了近期商品的损耗情况,通过近期盘点周期的数据计算得到。
整体求解过程概述(摘要)
商超(超市和零售店)在现代经济中扮演着至关重要的角色,然
而,它们在蔬菜商品管理中面临着多重挑战。这些挑战包括如何准确预测销售趋势、合理制定价格策略、以及有效制定补货计划等问题。解决这些问题对于商超来说至关重要,因为它们直接影响着销售收益、库存成本和客户满意度。因此,本研究旨在为商超提供一套全面的蔬菜商品管理策略,以帮助它们更好地应对这些挑战。
针对问题一,在蔬菜商品管理中,首要问题之一是如何准确预测
销售趋势。这包括了不同蔬菜品类的销售模式,如季节性销售高峰和低谷。我们需要深入了解哪些蔬菜在特定时间段内销售最活跃,以及它们之间的差异。这个问题的解决有助于商超更有针对性地制定促销策略和补货计划。
针对问题二,制定合理的价格策略对于商超至关重要,因为它们
需要平衡销售利润和客户价格敏感度。我们需要建立一个定价模型,考虑商品成本、预期销售量和销售利润等因素。这个模型将为每个蔬菜品类提供合理的售价建议,确保商超实现销售利润的最大化,同时提供具有竞争力的价格。
针对问题三,如何确定每个单品的补货量以及建议的定价策略是
另一个重要问题。我们需要通过组合优化方法,确定每个单品的最佳补货量和定价策略,以确保商超在未来某一天实现最佳盈利。这需要考虑预期利润、最小陈列量要求和其他约束条件。
针对问题四,更多的数据可以帮助商超更准确地预测市场需求,优化库存,制定更有效的定价策略,从而最大化收益。我们建议采集的数据包括:库存数据、竞争对手的价格数据、客户反馈、销售促销和广告活动的数据、季节性和趋势数据、供应链数据、宏观经济数据、商品的损耗数据、客户购买行为数据等。通过结合这些数据,商超可以更好地理解市场,满足客户需求,优化供应链,减少浪费,提高客户满意度,并最大化收益。
通过解决这些问题,我们的研究旨在为商超提供一套完整的蔬菜
商品管理策略,以帮助它们提高销售效益、降低库存成本,并提高客户满意度。
模型假设:
为了对问题一进行数学建模和分析,我们需要做出一些基本的假设。以下是一些可能的问题假设:
1. 历史销售数据能够代表未来的销售趋势:我们使用历史销售数据来预测未来的销售。
2. 蔬菜的损耗是固定的:我们使用平均损耗率来计算蔬菜的实际成本。
3. 商品的销售量与其定价有关:我们基于预测的销售量来制定定价策略。
4. 商超的销售空间是固定的:我们假设商超的销售空间在一段时间内是恒定的。
5. 所有的商品都有相同的陈列空间:每个商品的最小陈列量都是 2.5 千克。
6. 趋势假设:我们假设销售数据中可能存在长期的上升或下降趋势,这些趋势可以通过时间序列分解来识别。
7. 数据完整性假设:提供的销售数据被视为准确和完整,不包含任何误差或遗漏。
8. 稳定性假设:我们假设在观察期间,市场条件(例如消费者购买力、偏好等)保持相对稳定,这使得时间序列分析变得可行。
9. 季节性假设:蔬菜销售可能受到季节性影响,例如由于供应量、天气条件或节假日等原因,某些蔬菜在特定时期的销售量可能会增加或减少。
10. 独立性假设:除非通过数据明确显示出相关性,否则我们假设各个单品或品类之间的销售是独立的。
问题分析:
问题一的问题分析
为了分析蔬菜各品类及单品销售量的分布规律及相互关系,我们需要将这两个数据集合并,以便在一个数据框中查看每个蔬菜单品的销售情况和其所属的品类。然后,我们使用各种统计方法和可视化工具来进行了分析:首先将按品类对销售量进行总结,并可视化销售量的分布,其次计算每个单品的销售量,并进行可视化展示,然后通过时间序列分析各单品随时间变化的销售趋势,以确定哪些商品在特定时间段内的销售增长或下降和通过计算两两商品间的销售相关性,确定哪些商品经常一起购买。最终得出规律和相互关系
问题二的分析
根据题目和背景可知商超采用的是“成本加成定价”方法。由问题一可知蔬菜的供应品种在 4 月至 10 月较为丰富,而商超的销售空间有限。为了最大化收益,需要考虑的因素包括:蔬菜的进货成本、预期的销售量、市场需求、损耗率等。我们采用了线性回归方法预测未来一周的销售,然后基于预测的销售量和成本数据制定了定价策略。
问题三的分析
考虑到销售空间的限制,商超希望进一步制定单品的补货计划。需要确保可售单品总数控制在 27-33 个,且每个单品的订购量至少满足最小陈列量 2.5 千克的要求。我们使用了整个数据集的平均销售量作为预测值。使用贪心算法,我们选择了预期利润最高的 27-33 个单品,并为这些单品制定了定价策略。
问题四的分析
更多的数据可以帮助商超更准确地预测市场需求,优化库存,制定更有效的定价策略,从而最大化收益。我们建议采集的数据包括:库存数据、竞争对手的价格数据、客户反馈、销售促销和广告活动的数据、季节性和趋势数据、供应链数据、宏观经济数据、商品的损耗数据、客户购买行为数据等。通过结合这些数据,商超可以更好地理解市场,满足客户需求,优化供应链,减少浪费,提高客户满意度,并最大化收益。
模型的建立与求解整体论文缩略图
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
程序代码:(代码和文档not free)
pxy = pd.read_excel("data2pro1day.xlsx")
# 按销售日期、单品名称分组求和(只对 age 求和)
pxy2 = pxy.groupby(['销售日期','单品名称'])['销量(千
克)'].sum().reset_index()
pxy3 = pd.DataFrame(pxy2)
# 按销售日期、单品名称分组求和(只对 age 求和)
pxy2 = pxy.groupby(['销售日期','单品名称'])['销量(千
克)'].sum().reset_index()
pxy3 = pd.DataFrame(pxy2)
pxyy = pd.read_excel("不同品类销量日汇总表.xlsx")
# 按销售日期、单品名称分组求和(只对 age 求和)
pxy2 = pxyy.groupby(['销售日期','分类名称'])['销量(千克)','不同单品销
售价格'].sum().reset_index()
pxy3 = pd.DataFrame(pxy2)
pxy3.to_excel("不同品类销量与总销售价关系结果表.xlsx")
from pyecharts import ThemeRiver
import pandas as pd
# 导入数据
data_1 = pd.read_excel('不同品类销量月度汇总表.xlsx')
data_list = []
# 封装数据
for i in zip(data_1['销售月'],data_1['销量(千克)'],data_1['分类名称
']):data_list.append(list(i))
apk = ['水生根茎类','花叶类','花菜类','茄类','辣椒类','食用菌']
#colors_list=['#7f7f7f','#32CD32','#4169E1','#FAA460']#备用颜色列表
tr = ThemeRiver("")
tr.add(apk,data_list,is_random=True,is_label_show=True)
#tr.add(apk,data_list,is_random=True,is_label_show=True,label_color=c
olors_list)
tr.render("不同品类销量月度汇总河流图.html")
from pyecharts import Pie
import pandas as pd
vote_result = pd.read_excel("第二问 2023 年 6 月各品类销量占比.xlsx")
pie = Pie("2023 年 6 月份各品类销量占比环形图")
pie.add("",vote_result['分类名称'],vote_result['占比
'],center=[60,60],legend_orient="vertical",is_random=True,radius=[30,75],legend_pos="right",is_label_sh
ow=True)pie.render('2023 年 6 月份各品类销量占比环形图.html')
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
import numpy as np
# read data
data = pd.read_excel('data4zong.xlsx')
name = data['单品名称'].tolist()
rq = data['销售日期'].tolist()
qk = data['销量(千克)'].tolist()
sr = data['收入'].tolist()
dj = data['销售单价'].tolist()
key = ['2023-06-24', '2023-06-25', '2023-06-26', '2023-06-27', '2023-
06-28', '2023-06-29', '2023-06-30']
# data deal
dated = {time:[] for time in key}
for i in range(len(qk)):for time in key:if str(rq[i]).split(' ')[0] == time:temp = []temp.append(name[i])temp.append(qk[i])temp.append(dj[i])temp.append(sr[i])dated[time].append(temp)
# set name
nameset = list(set(name))
nameset.sort(key = name.index)
# fill with all names
for k, v in dated.items():vna = [item[0] for item in v]for cn in nameset:if cn not in vna:temp = []temp.append(cn)temp.append(0)temp.append(0)
temp.append(0)dated[k].append(temp)
# compute max sr
srd = {cn:[] for cn in nameset}
for cn in nameset:temp = []for k, v in dated.items():vna = [item for item in v]for vn in vna:if vn[0] == cn:temp.append(vn[-1])srd[cn] = sum(temp)
srd_sort = sorted(srd.items(), key=lambda x:x[1], reverse=True)
shour_max_name_list = [item[0] for item in srd_sort[:30]]
result = open('7 月 1 日的各单品补货量和定价策略.txt', 'a',
encoding='utf8')
for cn in nameset:teqk = []tedj = []for k, v in dated.items():vna = [item for item in v]for vn in vna:if vn[0] == cn:teqk.append(cn)tedj.append(cn)teqk.append(vn[1])tedj.append(vn[2])temp_name = teqk[0]if temp_name in shour_max_name_list:teqk = [teqk[i] for i in range(len(teqk)) if i%2 != 0]tedj = [tedj[i] for i in range(len(tedj)) if i%2 != 0]model_qk = ARIMA(np.array(teqk).reshape(-1, 1),
order=(1,1,1))model_dj = ARIMA(np.array(tedj).reshape(-1, 1),
order=(1,1,1))pred_qk = model_qk.fit().forecast(steps=10).tolist()pred_dj = model_dj.fit().forecast(steps=10).tolist()#pass#result.write(temp_name + '\t 补货量:' +
str(round(pred_qk[0], 3)) + '\t 定价:' + str(round(pred_dj[0], 1)) +
'\n')