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['销售价格']

代码解释:

  1. 导入所需的库

    • 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 用于设置全局字体,例如设置中文字体。
    • datetimetimedelta 用于处理日期和时间,例如获取日期、计算时间差等。
    • scipy.optimize.curve_fit 用于曲线拟合,找到最符合数据的曲线方程。
    • random 用于生成随机数,例如随机选择元素。
    • scipy.optimize.minimize 用于最小化函数,找到函数的最小值。
    • deap 用于遗传算法,实现基于遗传算法的优化。
    • re 用于正则表达式,进行字符串匹配和替换操作。
  2. 读取数据文件并预处理

    • data = pd.read_csv('./Q3_data.csv'):读取名为“Q3_data.csv”的CSV文件,并将其存储到名为“data”的DataFrame中。
    • data['销售日期'] = pd.to_datetime(data['销售日期']):将“销售日期”列转换为日期格式。
  3. 获取上周数据

    • 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中。
  4. 统计上周销售数量

    • item_counts = last_week_data['单品名称'].value_counts():统计上周每个单品的销售数量,并将结果存储到名为“item_counts”的Series中。
    • print(item_counts):打印统计结果。
  5. 绘制上周销售数量的柱状图

    • 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():显示图表。
  6. 计算每天每个单品的销售数量

    • 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”中。
  7. 预测未来一天的销售需求

    • daily_sales['预测需求'] = daily_sales.groupby('单品名称')['销售数量'].transform('mean'):计算每个单品在上周的平均销售数量,并将结果存储到“预测需求”列中。
    • daily_sales['批发价格'] = daily_sales.groupby('单品名称')['批发价格(元/千克)'].transform('mean'):计算每个单品的平均批发价格,并将结果存储到“批发价格”列中。
    • daily_sales['销售单价(元/千克)'] = daily_sales.groupby('单品名称')['销售单价(元/千克)'].transform('mean'):计算每个单品的平均销售单价,并将结果存储到“销售单价(元/千克)”列中。
  8. 准备预测数据

    • daily_sales = daily_sales[['销售日期', '单品名称', '预测需求','批发价格','平均损耗率','分类名称','销售单价(元/千克)']:仅保留“销售日期”、“单品名称”、“预测需求”、“批发价格”、“平均损耗率”、“分类名称”和“销售单价(元/千克)”列。
    • daily_sales['销售日期'] = '2023-07-01':将“销售日期”列设置为固定的日期。
    • daily_sales_predict = daily_sales.drop_duplicates():删除重复的行。
  9. 定义全局变量

    • S_profit = 0:定义全局变量“S_profit”,用于存储最大利润。
    • purchase_strategy = []:定义全局变量“purchase_strategy”,用于存储最佳进货策略。
    • sales_price = []:定义全局变量“sales_price”,用于存储最佳销售价格策略。
  10. 使用遗传算法优化进货量和销售价格

  • 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::如果当前利润大于全局最大利润,则更新全局最大利润、最佳进货策略和最佳销售价格策略。
  1. 创建进货量和销售价格的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中。代码中包含详细的注释,解释了每行代码的含义。

注意:

这段代码只是一个示例,实际应用中需要根据具体的业务需求进行修改。例如,可以添加其他影响利润的因素,例如运输成本、存储成本等。此外,还需要对遗传算法的参数进行调整,以获得最佳的优化效果。

建议:

  • 使用更强大的遗传算法库,例如 DEAPGAlib 等,可以提供更丰富的功能和更快的速度。
  • 使用更多的数据进行训练,例如历史销售数据、市场价格数据等,可以提高模型的准确性。
  • 使用更复杂的优化模型,例如多目标优化、强化学习等,可以处理更复杂的业务场景。

最后,祝你成功!

基于遗传算法的蔬菜进货量和销售价格优化策略

原文地址: https://www.cveoy.top/t/topic/emSU 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录