2023国赛C题 蔬菜类商品的自动定价与补货决策(上)

2023国赛C题

蔬菜类商品的自动定价与补货决策(上)


在这里插入图片描述

符号说明:

在这里插入图片描述

问题1


问题1主要的代码和思路在上一篇文章“数学建模实战块速入门”中已经进行了较为详细的展示,在问题一种要求我们从蔬菜单品和品类两个维度去分析各自之间的关系。我们采用的方法便是计算对应单品或者品类之间的相关系数;主要的相关系数有Spearmna相关系数或者**(Pearson)皮尔逊相关系数**等。(注意:能够适用皮尔逊相关的场合当然是优先使用皮尔逊相关,当数据展现的是非线性关系,或者不是正态分布的,或者存在较为明显的异常值考虑到斯皮尔曼相关系数对异常值不敏感可以选择斯皮尔曼相关系数而在分析各个品类在销量在时间上的分布后,我们发现其具有季节性起伏,因此两个单品或者品类之间难以建立线性的相关关系,因此选择反应单调变化趋势的斯皮尔曼相关系数就成为了更优的选择)。

在这里插入图片描述

在这里插入图片描述

使用python对原始数据进行处理和计算

#加载需要的python库,如果没有提前安装,使用pip install XXX进行安装,如果加载过慢超时,可以使用清华源等镜像下载。
import pandas as pd 
import numpy as np 
import cvxpy as cp 
import random 
import math 
from prophet import Prophet 
from datetime import datetime, timedelta 
import matplotlib.pyplot as plt 
from prophet.diagnostics import cross_validation, performance_metrics 
from sklearn.linear_model import LinearRegression 
from sklearn.metrics import mean_squared_error, mean_absolute_error 
import statsmodels.api as sm 

原始数据的处理示意图以及对应代码:

在这里插入图片描述

# 创建按品类划分的数据表 
df_items = pd.read_excel('附件1.xlsx', engine='openpyxl') # 从附件1读取蔬菜单品的数据 
df_sales = pd.read_excel('附件2.xlsx', engine='openpyxl') # 从附件2读取购买流水数据 
df_merged = pd.merge(df_sales, df_items, on='单品编码', how='left') # 通过蔬菜编码连接两个数据表 df_merged['金额'] = df_merged['销量(千克)'] * df_merged['销售单价(元/千克)'] # 计算每笔订单的销售金额(考虑退货,所以使用负值) 
df_merged.loc[df_merged['销售类型'] == '退货', '金额'] *= -1 
df_merged.loc[df_merged['销售类型'] == '退货', '销量(千克)'] *= -1 # 获取蔬菜单品每日平均价格 
daily_price = df_merged.groupby(['单品编码', '单品名称', '销售日期'])['销售单价(元/千克)'].mean().reset_index() # 按照蔬菜单品和销售日期来计算每日销售总销量、总金额 
daily_vol = df_merged.groupby(['单品编码', '单品名称', '销售日期'])['销量(千克)'].sum().reset_index() 
daily_sales = df_merged.groupby(['单品编码', '单品名称', '销售日期'])['金额'].sum().reset_index()
# 根据退货和销售金额计算退货率 
total_returned = df_merged[df_merged['销售类型'] == '退货'].groupby('单品编码')['金额'].sum() 
total_sales = df_merged[df_merged['销售类型'] == '销售'].groupby('单品编码')['金额'].sum() 
return_rate = (total_returned / total_sales).reset_index(name='退货率') # 合并数据获取每日平均价格 
pivot_price = daily_price.pivot_table(index=['单品编码', '单品名称'], columns='销售日期', values='销售单价(元/千克)', fill_value=0).reset_index() 
finalprice_df = pd.merge(df_items[['单品编码', '单品名称', '分类名称']], return_rate, on='单品编码', how='left') 
finalprice_df = pd.merge(finalprice_df, pivot_price, on=['单品编码', '单品名称'], how='left') # 合并数据获取每日销量 
pivot_vol = daily_vol.pivot_table(index=['单品编码', '单品名称'], columns='销售日期', values='销量(千克)', fill_value=0).reset_index() 
finalvol_df = pd.merge(df_items[['单品编码', '单品名称', '分类名称']], return_rate, on='单品编码', how='left') 
finalvol_df = pd.merge(finalvol_df, pivot_vol, on=['单品编码', '单品名称'], how='left') # 合并数据以获取每日销售额 
pivot_sales = daily_sales.pivot_table(index=['单品编码', '单品名称'], columns='销售日期', values='金额', fill_value=0).reset_index() 
finalsales_df = pd.merge(df_items[['单品编码', '单品名称', '分类名称']], return_rate, on='单品编码', how='left') 
finalsales_df = pd.merge(finalsales_df, pivot_sales, on=['单品编码', '单品名称'], how='left') # 保存为新的Excel文件 
finalprice_df.to_excel('output_price.xlsx', index=False, engine='openpyxl') 
finalvol_df.to_excel('output_vol.xlsx', index=False, engine='openpyxl') 
finalsales_df.to_excel('output_sales.xlsx', index=False, engine='openpyxl')

问题2


考虑商超以品类为单位做补货计划,请分析各蔬菜品类的销售总量与成本加成定价的关系,并给出各蔬菜品类未来一周(2023年7月1-7日)的日补货总量和定价策略, 使得商超收益最大。

问题分析: 问题二首先要求我们分析各蔬菜品类的销售总量和成本加定价的关系;从常识角度,蔬菜卖的越贵,销量就会减少,反之则会销量增加。因此我们可以判断出蔬菜品类的销售总量和成本加定价之间应该存在线性关系。

如何从数据中判断是否存在线性相关性? 我么可以考虑计算皮尔逊相关系数来判定。

皮尔逊相关系数可以用来度量两个变量之间的相关程度,其计算公式为:
ρ ( x , y ) = ∑ i = 1 n ( X i − X ˉ ) ( Y i − Y ˉ ) ∑ i = 1 n ( X i − X ˉ ) 2 ∑ i = 1 n ( Y i − Y ˉ ) 2 \rho\left(x,y\right)=\frac{\sum_{i=1}^n(X_i-\bar{X})(Y_i-\bar{Y})}{\sqrt{\sum_{i=1}^n(X_i-\bar{X})^2}\sqrt{\sum_{i=1}^n(Y_i-\bar{Y})^2}} ρ(x,y)=i=1n(XiXˉ)2 i=1n(YiYˉ)2 i=1n(XiXˉ)(YiYˉ)
如果判定结果为存在线性相关关系,我们则可以采用最小二乘等方法得到二者之间的线性回归方程

数据处理:

我们想要计算皮尔逊相关系数,那就要想办法得到各品类的销量数据以及各品类的成本加成定价。

销售数据在前面计算过,可以直接导入到Excel文件中:

# 每日销售量
pivot_class_vol.to_excel('daily_class_vol.xlsx', index=False, engine='openpyxl') 

某一时间段内(时间段可以为日、月、季度)的销售价格和批发价格分别由下式确定:

即:sum(每单单价*每单销量)/sum(每单销量)
P i ( t ) = ∑ p j ( t ) ⋅ q j ( t ) ∑ q j ( t ) , j ∈ 品类 i C i ( t ) = ∑ c j ( t ) ⋅ q j ( t ) ∑ q j ( t ) , j ∈ 品类 i P_{i}(t)=\frac{\sum p_j\left(t\right)\cdot q_j\left(t\right)}{\sum q_j\left(t\right)} , j\in\text{品类}i\\C_{i}(t)=\frac{\sum c_j\left(t\right)\cdot q_j\left(t\right)}{\sum q_j\left(t\right)} , j\in\text{品类}i Pi(t)=qj(t)pj(t)qj(t),j品类iCi(t)=qj(t)cj(t)qj(t),j品类i

"""
df_items = pd.read_excel('附件1.xlsx', engine='openpyxl') # 从附件1读取蔬菜单品的数据 
df_sales = pd.read_excel('附件2.xlsx', engine='openpyxl') # 从附件2读取购买流水数据 
df_merged = pd.merge(df_sales, df_items, on='单品编码', how='left') # 通过蔬菜编码连接两个数据表 df_merged['金额'] = df_merged['销量(千克)'] * df_merged['销售单价(元/千克)'] # 计算每笔订单的销售金额(考虑退货,所以使用负值) 
df_merged.loc[df_merged['销售类型'] == '退货', '金额'] *= -1 
df_merged.loc[df_merged['销售类型'] == '退货', '销量(千克)'] *= -1 
"""
# 按照蔬菜品类和销售日期来计算每日销售总销量、总金额 
daily_class_vol = df_merged.groupby(['分类编码', '分类名称', '销售日期'])['销量(千克)'].sum().reset_index() 
daily_class_sales = df_merged.groupby(['分类编码', '分类名称', '销售日期'])['金额'].sum().reset_index()


计算daily_class_vol 、daily_class_sales 使用了分组聚合的函数即groupby函数,我们对所有行按照分类编码和销售日期进行分组,并对每组元素进行对应的求和。我们便得到了各个品类在每一天的销量和销售金额。
下面是我们处理得到的结果:
在这里插入图片描述
我们希望得到的处理结果是时间作为行标签,蔬菜品类作为列标签,因此我们对数据进行了如下处理:

# 合并数据获取每日销量 
pivot_class_vol = daily_class_vol.pivot_table(index=['分类编码', '分类名称'], columns='销售日期', values='销量(千克)', fill_value=0).reset_index() 
# 合并数据以获取每日销售额 
pivot_class_sales = daily_class_sales.pivot_table(index=['分类编码', '分类名称'], columns='销售日期', values='金额', fill_value=0).reset_index() pivot_class_vol = pivot_class_vol.T
#pivot_class_vol.set_index('销售日期', inplace=True) # 把第一列日期设定为标签
dates = pivot_class_vol.index.tolist()[2:]
columns = pivot_class_vol.iloc[1]  # 取出第二行作为列名
pivot_class_vol = pivot_class_vol.iloc[2:].reset_index(drop=True)  # 去除前两行,并重置索引
pivot_class_vol.columns = columns  # 设置新的列名
pivot_class_vol.index = datespivot_class_sales = pivot_class_sales.T
columns = pivot_class_sales.iloc[1]  # 取出第二行作为列名
pivot_class_sales = pivot_class_sales.iloc[2:].reset_index(drop=True)  # 去除前两行,并重置索引
pivot_class_sales.columns = columns  # 设置新的列名
pivot_class_sales.index = dates
"""
分别计算日销售价格和日批发价格
"""

这个是我们希望得到的结果
在这里插入图片描述
下面我们按照前面给出的公式计算日成本加成定价,我们首先定义了存储计算结果的数据结构,然后带入公式计算。

import numpy as np
rows,cols = pivot_class_sales.shapedaily_class_price = np.zeros((rows, cols), dtype=int)
daily_class_price = pd.DataFrame(daily_class_price)
daily_class_price.columns = columns
daily_class_price.index = dates
# 日销售价格for i in pivot_class_sales.columns.tolist():for j in pivot_class_vol.index.tolist():if pivot_class_vol[i][j] == 0:daily_class_price[i][j] = 0  # 如果销量为0,则价格也为0else:daily_class_price[i][j] = pivot_class_sales[i][j] / pivot_class_vol[i][j]  # 计算日销售价格#daily_class_price[i] = pivot_class_sales[i] / pivot_class_vol[i]  # 计算日销售价格daily_class_price.to_excel('daily_class_price.xlsx', index=False, engine='openpyxl') 

在这里插入图片描述

采取同样的方式我们也可以计算日批发价格。

# 日批发价格
import pandas as pd 
#df_items = pd.read_excel('附件1.xlsx', engine='openpyxl') # 从附件1读取蔬菜单品的数据 
df_wholesale = pd.read_excel('附件3.xlsx', engine='openpyxl') # 从附件3读取蔬菜单品的批发数据
df_merged_wholesale = pd.merge(df_wholesale,df_items, on='单品编码', how='left') # 通过蔬菜编码连接两个数据表 #df_merged_wholesale = pd.merge(df_wholesale,df_items, on='单品编码', how='left') # 通过蔬菜编码连接两个数据表 
daily_vol = df_merged.groupby(['单品编码', '单品名称', '销售日期'])['销量(千克)'].sum().reset_index() daily_vol = daily_vol.rename(columns={'销售日期': '日期'})
###
merged_wholesale = pd.merge(daily_vol, df_merged_wholesale, on=['单品编码', '单品名称', '日期'], how='left')
# merged_wholesale = df_merged_wholesale.groupby(['单品编码', '单品名称', '日期'])['批发价格(元/千克)'].sum().reset_index()
merged_wholesale['批发金额'] = merged_wholesale['销量(千克)'] * merged_wholesale['批发价格(元/千克)']# 计算日批发价格需要使用销量*批发价格得到批发金额,计算每日批发金额/每日销量总和# ****************************************************** #
daily_class_wholesale = merged_wholesale.groupby(['分类编码', '分类名称', '日期'])['批发金额'].sum().reset_index() 
pivot_class_wholesale = daily_class_wholesale.pivot_table(index=['分类编码', '分类名称'], columns='日期', values='批发金额', fill_value=0).reset_index() 
pivot_class_wholesale = pivot_class_wholesale.T
#pivot_class_vol.set_index('销售日期', inplace=True) # 把第一列日期设定为标签
dates = pivot_class_wholesale.index.tolist()[2:]
columns = pivot_class_wholesale.iloc[1]  # 取出第二行作为列名
pivot_class_wholesale = pivot_class_wholesale.iloc[2:].reset_index(drop=True)  # 去除前两行,并重置索引
pivot_class_wholesale.columns = columns  # 设置新的列名
pivot_class_wholesale.index = dates
import numpy as np#rows,cols = pivot_class_sales.shape
daily_class_price = pd.read_excel('daily_class_price.xlsx', engine='openpyxl')
rows,cols = daily_class_price.shapedaily_class_wholesaleprice = np.zeros((rows, cols), dtype=int)
daily_class_wholesaleprice = pd.DataFrame(daily_class_price)
daily_class_wholesaleprice.columns = columns
daily_class_wholesaleprice.index = dates
# 这里的pivot_class_vol在计算每日价格时计算过,这边直接拿过来.for i in pivot_class_wholesale.columns.tolist():for j in pivot_class_vol.index.tolist():if pivot_class_vol[i][j] == 0:daily_class_wholesaleprice[i][j] = 0  # 如果销量为0,则价格也为0else:daily_class_wholesaleprice[i][j] = pivot_class_wholesale[i][j] / pivot_class_vol[i][j]  # 计算日销售价格#daily_class_price[i] = pivot_class_sales[i] / pivot_class_vol[i]  # 计算日销售价格daily_class_wholesaleprice.to_excel('daily_class_wholesaleprice.xlsx', index=False, engine='openpyxl') 

在这里插入图片描述

下面我们对成本加成定价与日销量计算皮尔逊相关系数,并进行最小二乘线性回归

import pandas as pd
daily_class_price = pd.read_excel('daily_class_price.xlsx', engine='openpyxl')
daily_class_wholesaleprice = pd.read_excel('daily_class_wholesaleprice.xlsx', engine='openpyxl')
daily_class_vol = pd.read_excel('daily_class_vol.xlsx', engine='openpyxl')
# 计算花叶类 日销量和成本加成定价 之间的皮尔逊相关系数# daily_class_price['花叶类'] 
pearson_xy = daily_class_wholesaleprice['花叶类'].corr(daily_class_vol['花叶类'], method='pearson')
print(f"变量X和Y之间的皮尔逊相关系数: {pearson_xy}")

在这里插入图片描述

进行最小二乘线性回归,并进行可视化展示:

import numpy as np
import matplotlib.pyplot as plt# 准备数据
#x = np.array([1, 2, 3, 4, 5])
#y = np.array([2, 4, 5, 4, 5])  # 注意:这些数据不是完美线性的,以展示拟合过程
x = np.array(daily_class_price['花叶类'].tolist())
y = np.array(daily_class_vol['花叶类'].tolist())# 使用numpy的polyfit函数进行线性拟合(1表示一次多项式,即线性)
# 返回拟合系数,其中第一个是斜率m,第二个是截距b
coefficients = np.polyfit(x, y, 1)
m, b = coefficients# 输出回归方程的参数
print(f"回归方程为: y = {m:.2f}x + {b:.2f}")# 使用拟合得到的参数进行预测
x_predict = np.linspace(min(x), max(x), 100)  # 生成一系列预测点
y_predict = m * x_predict + b# 可视化结果
plt.scatter(x, y, color='red', label='Data Points')
plt.plot(x_predict, y_predict, color='blue', label='Fitted Line')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Linear Least Squares Fitting')
plt.legend()
plt.show()

在这里插入图片描述


我们已经计算得到了一些关键行的指标,之后我们需要使用时间序列模型或者其他模型对未来一周的销量进行预测,并且开始建立以销售额的最大化为最优目标的优化求解模型,并使用一些求解算法来求解得到最终结果,这也是在下一篇文章的重点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146868.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

2024年中国研究生数学建模竞赛C题——解题思路

2024年中国研究生数学建模竞赛C题——解题思路 数据驱动下磁性元件的磁芯损耗建模——解决思路 二、问题描述 为解决磁性元件磁芯材料损耗精确计算问题,通过实测磁性元件在给定工况(不同温度、频率、磁通密度)下磁芯材料损耗的数据&#xf…

学习笔记——MMSR 自适应多模态融合的序列推荐

Adaptive Multi-Modalities Fusion in Sequential Recommendation Systems 前几天当我在阅读这篇论文的时候,在网上找到的相关资料很少,所以当时我读这篇论文的时候特别痛苦,精读了两天半.....所以现在我将自己学习笔记分享出来,…

服务器安全,你必须知道的六个知识点

服务器安全 如今没有什么是安全的。各种系统安全漏洞的数量呈爆炸式增长。令人担忧的主要原因之一是服务器安全性。 接下来,就如何提升服务器安全,写几点见解。 虽然很多企业在服务器的安全性方面做了足够多,但是,黑客仍然能够…

Python数据分析与可视化(Python绘图详解)

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

Qt圆角窗口

Qt圆角窗口 问题:自己重写了一个窗口,发现用qss设置圆角了,但是都不生效,不过子窗口圆角都生效了。 无边框移动窗口 bool eventFilter(QObject *watched, QEvent *evt) {static QPoint mousePoint;static bool mousePressed f…

群晖Docker如何修改配置文件(ContainerManager)

群晖Docker与其他linux操作系统的docker启动方式存在差异,默认的Docker配置文件位置也不一样。所以本章教程,主要介绍如何找到群晖Docker下的默认配置文件。 一、登录SSH 为了方便操作,需要开启SSH,并通过SSH链接到群晖NAS主机。登录之后,切换到root用户 sudo -i二、编辑配…

车载测试项目实操学习:CAN通信测试、UDS诊断测试、自动化测试、功能安全测试、CAN一致性测试、HIL测试:9-20

FOTA模块中OTA的知识点:1.测试过程中发现哪几类问题? 可能就是一个单键的ecu,比如升了一个门的ecu,他的升了之后就关不上,还有就是升级组合ecu的时候,c屏上不显示进度条。 2.在做ota测试的过程中&#xff…

企业文档管理系统哪个好?2024年热门的10款文档管理系统软件推荐

在信息化时代,企业每天都会生成海量的文档、数据和资料。 如何有效管理这些文档,确保信息安全、版本控制和协同办公顺畅,是每个企业都必须面对的挑战。 2024年,随着技术的不断进步,市场上涌现出了众多优秀的文档管理…

Selenium自动化测试环境搭建详解

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 本主要介绍以Java为基础,搭建Selenium自动化测试环境,并且实现代码编写的过程。 1、Selenium介绍 Selenium 1.0 包含 core、IDE、RC、gri…

C++进阶 set和map讲解

set 和 map set 和 multiset set set 类的介绍 set 是基于红黑树实现的有序容器。它的插入、删除、查找操作的时间复杂度均为 O(log n)。遍历时,set 的迭代器按照中序遍历,因此它总是以升序排列元素。 set 的声明如下,T 表示 set 的关键字类…

Kubernetes集群部署(kubernetes)

三台主机恢复到docker快照状态; 检查驱动器类型为sytemd; 设置各个节点的主机名; 然后同步会话,修改hosts文件; 在k8s运行过程中不建议使用交换分区; 关闭交换分区; 但是这种方法是临时性的&am…

JavaSE--零基础的开始笔记02:基础语法--标识符,关键字,变量

一.标识符 Java 语言中,对各种变量、方法和类等要素命名时使用的字符序列称为标识符。 Java 标识符有如下命名规则: 标识符由字母、下划线“_” 、美元符“$”或数字组成。 标识符应以字母、下划线 、美元符开头。 Java 标识符大小写敏感&#xff0c…

【Linux笔记】虚拟机内Linux内容复制到宿主机的Window文件夹(文件)中

一、共享文件夹 I、Windows宿主机上创建一个文件夹 目录:D:\Centos_iso\shared_files II、在VMware中设置共享文件夹 1、打开VMware Workstation 2、选择需要设置的Linux虚拟机,点击“编辑虚拟机设置”。 3、在“选项”标签页中,选择“共…

初识模版!!

初识模版 1.泛型编程1.1 如何实现一个交换函数呢(使得所有数据都可以交换)?1.2 那可以不可以让编译器根据不同的类型利用该模子来生成代码呢? 2.模版类型2.1 模版概念2.2 函数模版的原理2.3 函数模板的实例化2.4 模板参数的匹配原…

【C++初阶】探索STL之——String类的模拟实现

【C初阶】String类的模拟实现 1.string类2.string类的构造和赋值实现3.类的析构实现4.类的iterator5.类的修改(Modify)实现6.类的capacity实现7.类access的实现8.类relational operators的实现9.类find、insert、erase的实现10.operator>>和operat…

官方力荐:LDR6020 PD技术,让Type-C接口充放OTG不再是梦!

PD(Power Delivery)芯片赋能Type-C接口:解锁充电与数据传输的双重魔法 一、PD芯片的科技内核 高速充电与智能数据传输: PD芯片深谙USB Power Delivery规范,支持高功率传输协议,实现快速充电的同时&#x…

数据中台过时了?为什么现在都在说数据飞轮

数据中台作为一种集中式的数据管理与服务平台,在解决企业数据管理困境中发挥着重要作用,如数据孤岛、数据标准化、数据共享与复用等问题。通过统一的数据采集、处理、存储和服务,数据中台构建了一个全局性的数据枢纽,满足各业务部…

【YOLO目标检测道路交通标识数据集】共2838张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式:YOLO格式 图片数量:2838 标注数量(txt文件个数):2838 标注类别数:56 标注类别名称: mand_straight forb_right prio_priority_road info_crosswalk forb_weight_over_3.5t inf…

亿发工单系统:让任务风平浪静

在现代企业的日常运营中,工单管理系统已经成为必不可少的工具,无论是生产制造、IT运维,还是客服支持,工单系统的存在都是为了高效处理任务、跟踪进展、分配资源。然而,现实中的工单管理,往往不是“风平浪静…

【FPGA】编程方式

FPGA编程方式 1 什么是PLD?2 什么是颗粒度?3 可编程逻辑器件的编程方式有哪些?3.1 SRAM 编程技术3.2 Flash/EEPROM 编程技术3.3 反熔丝编程技术3.4 编程技术比较 参考资料 1 什么是PLD? 可编程逻辑器件 英文全称为:pr…