基于遗传算法的蔬菜进货量和销售价格优化策略
import pandas as pd # 用于数据处理
import numpy as np # 用于数值计算
import matplotlib.pyplot as plt # 用于数据可视化
import seaborn as sns # 用于数据可视化
import os # 用于文件操作
import warnings # 用于忽略警告
warnings.filterwarnings('ignore')
from sklearn.preprocessing import LabelEncoder # 用于标签编码
from sklearn.model_selection import train_test_split # 用于数据集划分
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report # 用于模型评估
from sklearn.linear_model import LogisticRegression # 用于逻辑回归建模
from sklearn.tree import DecisionTreeClassifier # 用于决策树建模
import matplotlib.font_manager as fm # 用于设置全局字体
from datetime import datetime, timedelta # 用于处理日期和时间
from scipy.optimize import curve_fit # 用于曲线拟合
import random # 用于随机选择
from scipy.optimize import curve_fit # 用于曲线拟合
from scipy.optimize import minimize # 用于最小化
from deap import base, creator, tools, algorithms # 用于遗传算法
import re # 用于正则表达式
# 设置全局字体
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['SimHei']
# 读取数据文件并将销售日期转换为日期格式
data = pd.read_csv('./Q3_data.csv')
data['销售日期'] = pd.to_datetime(data['销售日期'])
# 获取上周的开始日期和结束日期
e_date = data['销售日期'].max()
s_date = e_date - pd.Timedelta(days=6)
# 根据上周的开始日期和结束日期筛选出上周的数据
last_week_data = data.loc[(data['销售日期'] >= s_date) & (data['销售日期'] <= e_date)]
# 统计上周每个单品的销售数量
item_counts = last_week_data['单品名称'].value_counts()
# 打印统计结果
print(item_counts)
# 绘制上周销售数量的柱状图
plt.figure(figsize=(16, 8))
last_week_data['单品名称'].value_counts().plot(kind='bar', figsize=(16, 8), fontsize=14)
plt.xlabel('单品名称', fontproperties=font)
plt.ylabel('销售数量', fontproperties=font)
plt.title('上周销售数量', fontproperties=font)
plt.show()
# 根据销售日期和单品名称对数据进行分组,并计算每天每个单品的销售数量
daily_sales = last_week_data.groupby(['销售日期', '单品名称']).size().reset_index(name='销售数量')
daily_sales = pd.merge(daily_sales, data[['销售日期', '单品名称', '销售单价(元/千克)', '批发价格(元/千克)', '平均损耗率','分类名称']], on=['销售日期', '单品名称'], how='left')
# 将每个单品的上周的平均值作为未来一天的预测值
daily_sales['预测需求'] = daily_sales.groupby('单品名称')['销售数量'].transform('mean')
daily_sales['批发价格'] = daily_sales.groupby('单品名称')['批发价格(元/千克)'].transform('mean')
daily_sales['销售单价(元/千克)'] = daily_sales.groupby('单品名称')['销售单价(元/千克)'].transform('mean')
# 存储到新的dataframe中
daily_sales = daily_sales[['销售日期', '单品名称', '预测需求','批发价格','平均损耗率','分类名称','销售单价(元/千克)']]
daily_sales['销售日期'] = '2023-07-01'
# 去重
daily_sales_predict = daily_sales.drop_duplicates()
# 定义全局变量S_profit和列表purchase_strategy和sales_price
S_profit = 0
purchase_strategy = []
sales_price = []
# 进行全局优化,随机选择进货量和销售价格,计算利润
for i in range(0,1000000):
# 初始化列表
lst = [0] * 49
# 随机选择元素
while sum(lst) < 27 or sum(lst) > 33:
lst = [random.randint(0, 1) for _ in range(49)]
num_lst = np.multiply( np.array(lst) , np.array([random.uniform(2.5, 30) for _ in range(49)])) #进货量
cost_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['平均损耗率'])) / 100 #损耗量
# 将lst转换为布尔列表
bool_lst = [bool(x) for x in lst]
# 使用布尔索引筛选DataFrame
filtered_df = daily_sales_predict[bool_lst]
num_veg = len(filtered_df['分类名称'].unique())
num_veg_1 = len(filtered_df['单品名称'].unique())
cost_num_lst = np.multiply( num_lst, cost_lst) #损耗量
max_sale_lst = num_lst - cost_num_lst #最大销售量
p_lst = np.multiply( num_lst, np.array(daily_sales_predict['批发价格'])) #进货价格
price_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['销售单价(元/千克)'])) #销售价格
sale_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['预测需求'])) #销售量
actually_sale = np.where(max_sale_lst- sale_lst < 0, max_sale_lst , max_sale_lst- sale_lst )
profit_lst = np.multiply( actually_sale , price_lst) - p_lst #利润
s_profit = sum(profit_lst) + 5 * num_veg + num_veg_1 #总利润
if s_profit > S_profit:
S_profit = s_profit
purchase_strategy = num_lst.tolist()
sales_price = price_lst.tolist()
S_profit = s_profit
# 创建进货量和销售价格的DataFrame
purchase_strategy_df = pd.DataFrame()
purchase_strategy_df= pd.DataFrame(daily_sales_predict['单品名称'], columns=['单品名称'])
purchase_strategy_df['进货量'] = pd.DataFrame(purchase_strategy, columns=['进货量'])['进货量']
sales_price_df = pd.DataFrame(sales_price, columns=['销售价格'])
purchase_strategy_df['销售价格'] = sales_price_df['销售价格']
代码解释:
-
导入所需的库
pandas用于数据处理,例如读取CSV文件、数据清洗、数据操作等。numpy用于数值计算,例如数组操作、矩阵运算等。matplotlib.pyplot用于绘制图表,例如柱状图、折线图等。seaborn用于绘制更美观的统计图表。os用于文件操作,例如读取文件、创建文件夹等。warnings用于忽略警告信息。sklearn.preprocessing.LabelEncoder用于标签编码,将字符串标签转换为数字标签。sklearn.model_selection.train_test_split用于将数据集划分为训练集和测试集。sklearn.metrics.accuracy_score, confusion_matrix, classification_report用于评估机器学习模型的性能。sklearn.linear_model.LogisticRegression用于逻辑回归建模。sklearn.tree.DecisionTreeClassifier用于决策树建模。matplotlib.font_manager用于设置全局字体,例如设置中文字体。datetime和timedelta用于处理日期和时间,例如获取日期、计算时间差等。scipy.optimize.curve_fit用于曲线拟合,找到最符合数据的曲线方程。random用于生成随机数,例如随机选择元素。scipy.optimize.minimize用于最小化函数,找到函数的最小值。deap用于遗传算法,实现基于遗传算法的优化。re用于正则表达式,进行字符串匹配和替换操作。
-
读取数据文件并预处理
data = pd.read_csv('./Q3_data.csv'):读取名为“Q3_data.csv”的CSV文件,并将其存储到名为“data”的DataFrame中。data['销售日期'] = pd.to_datetime(data['销售日期']):将“销售日期”列转换为日期格式。
-
获取上周数据
e_date = data['销售日期'].max():获取数据集中“销售日期”列的最大值,即最近的日期。s_date = e_date - pd.Timedelta(days=6):从最近的日期减去6天,得到上周的开始日期。last_week_data = data.loc[(data['销售日期'] >= s_date) & (data['销售日期'] <= e_date)]:筛选出“销售日期”介于上周开始日期和结束日期之间的行,并将结果存储到名为“last_week_data”的DataFrame中。
-
统计上周销售数量
item_counts = last_week_data['单品名称'].value_counts():统计上周每个单品的销售数量,并将结果存储到名为“item_counts”的Series中。print(item_counts):打印统计结果。
-
绘制上周销售数量的柱状图
plt.figure(figsize=(16, 8)):创建一张尺寸为16x8英寸的图。last_week_data['单品名称'].value_counts().plot(kind='bar', figsize=(16, 8), fontsize=14):绘制上周销售数量的柱状图,并设置柱状图的大小和字体大小。plt.xlabel('单品名称', fontproperties=font):设置横轴标签为“单品名称”。plt.ylabel('销售数量', fontproperties=font):设置纵轴标签为“销售数量”。plt.title('上周销售数量', fontproperties=font):设置图标题为“上周销售数量”。plt.show():显示图表。
-
计算每天每个单品的销售数量
daily_sales = last_week_data.groupby(['销售日期', '单品名称']).size().reset_index(name='销售数量'):根据“销售日期”和“单品名称”对“last_week_data”进行分组,并计算每个组的大小,即每天每个单品的销售数量,并将结果存储到名为“daily_sales”的DataFrame中。daily_sales = pd.merge(daily_sales, data[['销售日期', '单品名称', '销售单价(元/千克)', '批发价格(元/千克)', '平均损耗率','分类名称']], on=['销售日期', '单品名称'], how='left'):将“daily_sales”与“data”进行合并,合并的依据是“销售日期”和“单品名称”,并将“销售单价(元/千克)”、“批发价格(元/千克)”、“平均损耗率”和“分类名称”列添加到“daily_sales”中。
-
预测未来一天的销售需求
daily_sales['预测需求'] = daily_sales.groupby('单品名称')['销售数量'].transform('mean'):计算每个单品在上周的平均销售数量,并将结果存储到“预测需求”列中。daily_sales['批发价格'] = daily_sales.groupby('单品名称')['批发价格(元/千克)'].transform('mean'):计算每个单品的平均批发价格,并将结果存储到“批发价格”列中。daily_sales['销售单价(元/千克)'] = daily_sales.groupby('单品名称')['销售单价(元/千克)'].transform('mean'):计算每个单品的平均销售单价,并将结果存储到“销售单价(元/千克)”列中。
-
准备预测数据
daily_sales = daily_sales[['销售日期', '单品名称', '预测需求','批发价格','平均损耗率','分类名称','销售单价(元/千克)']:仅保留“销售日期”、“单品名称”、“预测需求”、“批发价格”、“平均损耗率”、“分类名称”和“销售单价(元/千克)”列。daily_sales['销售日期'] = '2023-07-01':将“销售日期”列设置为固定的日期。daily_sales_predict = daily_sales.drop_duplicates():删除重复的行。
-
定义全局变量
S_profit = 0:定义全局变量“S_profit”,用于存储最大利润。purchase_strategy = []:定义全局变量“purchase_strategy”,用于存储最佳进货策略。sales_price = []:定义全局变量“sales_price”,用于存储最佳销售价格策略。
-
使用遗传算法优化进货量和销售价格
for i in range(0,1000000):循环100万次。lst = [0] * 49:创建一个包含49个0的列表,用于表示每个单品是否进货(0表示不进货,1表示进货)。while sum(lst) < 27 or sum(lst) > 33::循环直到列表中1的个数在27到33之间。lst = [random.randint(0, 1) for _ in range(49)]:随机生成一个包含49个0或1的列表。num_lst = np.multiply( np.array(lst) , np.array([random.uniform(2.5, 30) for _ in range(49)])):根据列表“lst”和随机生成的进货量范围,计算每个单品的进货量。cost_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['平均损耗率'])) / 100:根据列表“lst”和“平均损耗率”列,计算每个单品的损耗量。bool_lst = [bool(x) for x in lst]:将列表“lst”转换为布尔列表。filtered_df = daily_sales_predict[bool_lst]:根据布尔列表“bool_lst”筛选“daily_sales_predict”DataFrame。num_veg = len(filtered_df['分类名称'].unique()):统计筛选后的DataFrame中“分类名称”列的唯一值个数,即蔬菜种类个数。num_veg_1 = len(filtered_df['单品名称'].unique()):统计筛选后的DataFrame中“单品名称”列的唯一值个数,即单品个数。cost_num_lst = np.multiply( num_lst, cost_lst):计算每个单品的损耗量。max_sale_lst = num_lst - cost_num_lst:计算每个单品的最大销售量。p_lst = np.multiply( num_lst, np.array(daily_sales_predict['批发价格'])):计算每个单品的进货价格。price_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['销售单价(元/千克)'])):计算每个单品的销售价格。sale_lst = np.multiply( np.array(lst) , np.array(daily_sales_predict['预测需求'])):计算每个单品的预测销售量。actually_sale = np.where(max_sale_lst- sale_lst < 0, max_sale_lst , max_sale_lst- sale_lst ):计算每个单品的实际销售量,如果最大销售量小于预测销售量,则实际销售量等于最大销售量,否则等于最大销售量减去预测销售量。profit_lst = np.multiply( actually_sale , price_lst) - p_lst:计算每个单品的利润。s_profit = sum(profit_lst) + 5 * num_veg + num_veg_1:计算总利润,包括每个单品的利润、蔬菜种类个数和单品个数的奖励。if s_profit > S_profit::如果当前利润大于全局最大利润,则更新全局最大利润、最佳进货策略和最佳销售价格策略。
- 创建进货量和销售价格的DataFrame
purchase_strategy_df = pd.DataFrame():创建一个空的DataFrame。purchase_strategy_df= pd.DataFrame(daily_sales_predict['单品名称'], columns=['单品名称']):将“单品名称”列添加到DataFrame中。purchase_strategy_df['进货量'] = pd.DataFrame(purchase_strategy, columns=['进货量'])['进货量']:将最佳进货策略添加到DataFrame中。sales_price_df = pd.DataFrame(sales_price, columns=['销售价格']):创建一个包含最佳销售价格策略的DataFrame。purchase_strategy_df['销售价格'] = sales_price_df['销售价格']:将最佳销售价格策略添加到“purchase_strategy_df”中。
总结
这段代码使用遗传算法来优化蔬菜进货量和销售价格,以最大化利润为目标。代码中首先读取数据并进行预处理,然后使用遗传算法进行优化,最后将最佳进货策略和销售价格策略存储到DataFrame中。代码中包含详细的注释,解释了每行代码的含义。
注意:
这段代码只是一个示例,实际应用中需要根据具体的业务需求进行修改。例如,可以添加其他影响利润的因素,例如运输成本、存储成本等。此外,还需要对遗传算法的参数进行调整,以获得最佳的优化效果。
建议:
- 使用更强大的遗传算法库,例如
DEAP、GAlib等,可以提供更丰富的功能和更快的速度。 - 使用更多的数据进行训练,例如历史销售数据、市场价格数据等,可以提高模型的准确性。
- 使用更复杂的优化模型,例如多目标优化、强化学习等,可以处理更复杂的业务场景。
最后,祝你成功!
原文地址: https://www.cveoy.top/t/topic/emSU 著作权归作者所有。请勿转载和采集!