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')