【2023Mathorcup大數(shù)據(jù)】B題 電商零售商家需求預測及庫存優(yōu)化問題 python代碼解析
1 題目
2023 年MathorCup 高校數(shù)學建模挑戰(zhàn)賽——大數(shù)據(jù)競賽賽道B:電商零售商家需求預測及庫存優(yōu)化問題電商平臺存在著上千個商家,他們會將商品貨物放在電商配套的倉庫,電商平臺會對這些貨物進行統(tǒng)一管理。通過科學的管理手段和智能決策,大數(shù)據(jù)智能驅(qū)動的供應鏈可以顯著降低庫存成本,同時保證商品的按時履約。一般來說,以上供應鏈優(yōu)化問題會包含以下方面:
(1)需求預測
預測往往是智能供應鏈的決策基礎,它可以讓管理者提前預知各地的需求,從而將庫存提前放在靠近需求的倉庫中,此時的預測任務為:根據(jù)歷史一段時間的需求量,預測各倉庫中各商品未來需求,“預測維度”即為不同商家在各倉庫中存放的各種商品每天的數(shù)量。一般來說,企業(yè)會首先根據(jù)數(shù)據(jù)的歷史情況,分析出需求量序列的數(shù)理特征,對相似的需求量序列進行歸類,并根據(jù)分類結(jié)果做到更加精準的預測。預測準確率有很多評價指標,較常用的指標為 1-wmape,定義如下:
1
?
w
m
a
p
e
=
1
?
∑
∣
y
i
?
y
i
^
∣
∑
y
i
1-wmape = 1-\frac{\sum {|y_i-\hat{y_i}|}}{\sum{y_i}}
1?wmape=1?∑yi?∑∣yi??yi?^?∣?
其中 y i y_i yi?為第個序列(商家在各倉庫中存放的各種商品每天的數(shù)量)的真實需求量, y i ^ \hat{y_i} yi?^?為第個序列的預測需求量。
然而,在實際的電商供應鏈預測任務中,常常會出現(xiàn)多種不同的問題。例如,部分商品的銷售時間過短、倉庫存在新增或切換等情況,導致該預測維度下歷史數(shù)據(jù)過少;另外,部分大型促銷期間貨量的陡增并由此帶來的不規(guī)律性,也給需求量的精準預測帶來了不小的難度。此時便需要通過算法得到歷史一般規(guī)律,找出相似的歷史情況(如相似的倉或商品),從而實現(xiàn)精準預測。
(2)庫存優(yōu)化
為了有效管理庫存水平,企業(yè)通常會制定各種庫存策略來控制商品的補貨頻次和補貨量。定期盤點庫存策略(s,S)是一種常見的庫存策略,其中
s 表示該種策略下的庫存下限,S 為庫存上限。在這種策略中,企業(yè)會每隔一段固定時間查看庫存水平,盤點之間的間隔設為盤點周期(NRT)。如果在盤點時庫存水平T 低于最小庫存水平s,則會將庫存補充至S,此時的補貨量 Q = S ? T,如果在盤點時庫存水平高于 s,則不進行補充,直到下一次庫存盤點。同時需要考慮到,在每次發(fā)起補貨后,補充的貨物會經(jīng)過一定時間后才能到達當前倉庫,這個時間間隔為提前期(LT)。
使用以上的庫存策略,管理者需要對兩個方面進行權衡取舍。一方面,為了及時滿足用戶訂單,公司需要保有大量庫存以防止缺貨;另一方面,庫存水位升高帶來了過高的庫存成本。庫存優(yōu)化的目標主要為:
1) 降低庫存總持有成本,可由單位持有成本h 得到(一件商品存儲一天產(chǎn)生的成本);
2) 滿足服務水平:確保有足夠的產(chǎn)品可以及時滿足客戶需求,降低總?cè)必洺杀?,可由缺貨成本得到(每天每缺一件商品產(chǎn)生的成本);
3) 降低庫存周轉(zhuǎn)天數(shù):庫存周轉(zhuǎn)天數(shù)越小,表示庫存的流動性越好,企業(yè)的庫存管理效率越高。
服務水平及庫存周轉(zhuǎn)天數(shù)計算公式為:
$$
服務水平=\frac{被滿足的商品件數(shù)}{實際需求總件數(shù)} × 100 % \
庫存周轉(zhuǎn)天數(shù) =\frac{期初庫存書劉昂+期末庫存數(shù)量}{2}× \frac{計算時間段內(nèi)天數(shù)}{計算時間段內(nèi)總銷量}
$$
現(xiàn)有一張電商零售商家的歷史出貨量表(附件 1),給出了歷史 6 個月各商家存放在電商不同倉庫的商品每天的出貨量。假設該出貨量即為歷史各商品在各倉庫的需求量。同時,還可以取到各商品、商家、倉庫的信息(附件 2-4),例如分類、品牌、生效日期等,這些信息的選擇和引入會幫助更好的預測并管理供應鏈中的庫存。
1.1 初賽問題
問題一: 使用附件 1-4 中的數(shù)據(jù), 預測出各商家在各倉庫的商品2023-05-16 至 2023-05-30 的需求量,請將預測結(jié)果填寫在結(jié)果表 1 并上傳至競賽平臺,并對你們模型的預測性能進行評價。另外請討論:根據(jù)數(shù)據(jù)分析及建模過程,這些由商家、倉庫、商品形成的時間序列如何分類,使同一類別在需求上的特征最為相似?
**問題二:**現(xiàn)有一些新出現(xiàn)的商家+倉庫+商品維度(附件 5),導致這種情況出現(xiàn)的原因可能是新上市的商品,或是改變了某些商品所存放的倉庫。請討論這些新出現(xiàn)的預測維度如何通過歷史附件 1 中的數(shù)據(jù)進行參考,找到相似序列并完成這些維度在 2023-05-16 至 2023-05-30 的預測值。請把預測結(jié)果填寫在結(jié)果表 2,并上傳至競賽平臺。
**問題三:**每年 6 月會出現(xiàn)規(guī)律性的大型促銷,為需求量的精準預測以及履約帶來了很大的挑戰(zhàn)。附件 6 給出了附件 1 對應的商家+倉庫+商品維度在去年雙十一期間的需求量數(shù)據(jù),請參考這些數(shù)據(jù),給出 2023-06-01 至2023-06-20 的預測值。請把預測結(jié)果填寫在結(jié)果表 3,并上傳至競賽平臺。
注:結(jié)果表 1-3 打包一個壓縮包,“結(jié)果表.zip”,提交 zip 文件到競賽系統(tǒng)中。
附件1-4的字段說明:
附件 1:商家歷史出貨量表
字段名 | 字段類型 | 描述 |
---|---|---|
seller_no | String | 商家編碼 |
product_no | String | 商品編碼 |
warehouse_no | String | 倉庫編碼 |
date | String | 日期 |
qty | Float | 出貨量(可看做需求量) |
附件 2:商品信息表
字段名 | 字段類型 | 描述 |
---|---|---|
product_no | String | 商品編碼 |
category1 | String | 商品一級分類 |
category2 | String | 商品二級分類 |
category3 | String | 商品三級分類 |
附件 3:商家信息表
字段名 | 字段類型 | 描述 |
---|---|---|
seller_no | String | 商家編碼 |
seller_category | String | 商家分類 |
inventory_category | String | 庫存分類 |
seller_level | String | 商家規(guī)模 |
附件 4:倉庫信息表
字段名 | 字段類型 | 描述 |
---|---|---|
warehouse_no | String | 倉庫編碼 |
warehouse_category | String | 倉庫類別 |
warehouse_region | String | 倉庫區(qū)域 |
2 問題分析
2.1 問題一
(1)數(shù)據(jù)預處理:讀取附件1-4的數(shù)據(jù)文件,進行數(shù)據(jù)清洗和轉(zhuǎn)換,可考慮進行以下操作:
- 將“日期”字段轉(zhuǎn)換為datetime格式,并提取出年、月、日等信息;
- 將附件2、3、4中的分類信息進行Label Encoding,將分類信息轉(zhuǎn)換為數(shù)字標簽;
- 可以通過統(tǒng)計分析、可視化等手段對數(shù)據(jù)進行初步探索和分析,例如:
- 商家、倉庫、商品的數(shù)量分布情況;
- 商家、倉庫、商品之間的相關性分析等。
(2)特征工程:對表格進行透視或分組操作,生成對應時間序列的統(tǒng)計特征,例如:
- 統(tǒng)計每個商家在每個倉庫中每天/周/月的平均銷量、總銷量、銷售額等信息;
- 構建時間窗口特征,例如每個商家在每個倉庫中最近1周、1個月、3個月、6個月等時間段內(nèi)的銷售量、均值以及波動情況等。
(3)時間序列預測:針對每個商家、倉庫、商品的時間序列統(tǒng)計特征,使用ARIMA、Prophet、LSTM等時間序列預測模型進行預測,并得出下一個時間段內(nèi)的需求量預測值。代碼實現(xiàn)以ARIMA為例。
(4)結(jié)果輸出:按照表5的格式輸出預測結(jié)果
(5)分類方法:可以考慮聚類算法,將同一類別的商家、倉庫、商品按照需求量相似性進行分組,然后對每一個簇進一步分析,例如:
- K-means算法:基于樣本的相似性對樣本進行分群;
- 層次聚類算法:將潛在的類別從候選集合中逐層聚合。
(6)相似性評測:通過度量分類以上聚類結(jié)果的質(zhì)量,計算同一類別內(nèi)的商家、倉庫、商品之間的相似程度,以便為商家提供更加精準的預測及建議。常用的質(zhì)量評價標準有輪廓系數(shù)、Calinski-Harabasz指數(shù)、Davies-Bouldin指數(shù)等。
(7)反饋優(yōu)化:根據(jù)預測結(jié)果和分類分析的結(jié)果,進一步分析結(jié)論,給商家?guī)讉€建議和優(yōu)化方案。
2.2 問題二
(1)對附件1中所有商家、倉庫、商品組合,按時間順序生成其歷史出貨量時間序列,對于新增的商家+倉庫+商品維度在附件5中可以視為只有一條歷史記錄。
(2)對于新增的商家+倉庫+商品維度,在附件1中搜索與其最為相似的歷史時間序列,可以使用聚類分析或其他相似度度量方法進行相似性計算。代碼中采用歐式距離的方式。使用cdist()函數(shù)計算子集(seller_no和warehouse_no相同)的qty列和附件5的qty列之間計算歐氏距離。最后使用np.argmin()函數(shù)找到距離數(shù)組distances中具有最小值的索引值。這表示找到了在附件5中最相似的歷史序列。
(3)將找到的最為相似的歷史時間序列作為該新增維度的需求量時間序列,使用與問題一相同的方法進行預測并填寫結(jié)果表2。
2.3 問題三
(1)使用附件1中給出的商家+倉庫+商品的歷史需求量數(shù)據(jù),加上附件6中相應的需求量數(shù)據(jù),按照時間順序生成歷史需求量時間序列。
(2)對歷史時間序列進行特征工程,提取時間維度,周幾、月份、節(jié)假日等特征,并進行預處理操作(如平滑、滑動平均等)。
(3)使用時間序列預測模型進行訓練,并對2023-06-01 至2023-06-20 的需求量進行預測。
3 代碼實現(xiàn)
3.1 問題一
import pandas as pd
import numpy as np
from datetime import datetime
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
plt.rcParams['font.sans-serif'] = ['STSong']
(1)數(shù)據(jù)預處理
對類別特征編碼
# 數(shù)據(jù)預處理
# 讀取商家歷史出貨量表
df_sales = pd.read_excel('附件表/附件1-商家歷史出貨量表.xlsx')
# 將日期字段轉(zhuǎn)換為datetime格式
df_sales['date'] = pd.to_datetime(df_sales['date'])
df_sales['year'] = df_sales['date'].dt.year
df_sales['month'] = df_sales['date'].dt.month
df_sales['day'] = df_sales['date'].dt.day
# 讀取商品信息表
df_product = pd.read_excel('附件表/附件2-商品信息表.xlsx')
# 使用Label Encoder對商品分類信息進行編碼
le = LabelEncoder()
df_product['category1'] = le.fit_transform(df_product['category1'])
df_product['category2'] = le.fit_transform(df_product['category2'])
df_product['category3'] = le.fit_transform(df_product['category3'])
# 讀取商家信息表
df_seller = pd.read_excel('附件表/附件3-商家信息表.xlsx')
# 使用Label Encoder對商家分類信息進行編碼
df_seller['seller_category'] = le.fit_transform(df_seller['seller_category'])
df_seller['inventory_category'] = le.fit_transform(df_seller['inventory_category'])
df_seller['seller_level'] = le.fit_transform(df_seller['seller_level'])
# 讀取倉庫信息表
df_warehouse = pd.read_excel('附件表/附件4-倉庫信息表.xlsx')
# 使用Label Encoder對倉庫分類信息進行編碼
df_warehouse['warehouse_category'] = le.fit_transform(df_warehouse['warehouse_category'])
df_warehouse['warehouse_region'] = le.fit_transform(df_warehouse['warehouse_region'])
(2)統(tǒng)計商家、倉庫、商品的數(shù)量分布情況
# 統(tǒng)計商家、倉庫、商品的數(shù)量分布情況
seller_count = df_sales['seller_no'].nunique()
warehouse_count = df_sales['warehouse_no'].nunique()
product_count = df_sales['product_no'].nunique()
print("商家數(shù)量:", seller_count)
print("倉庫數(shù)量:", warehouse_count)
print("商品數(shù)量:", product_count)
# 商家、倉庫、商品之間的相關性分析
sales_groupby_seller = df_sales.groupby('seller_no')['qty'].sum().reset_index()
sales_groupby_warehouse = df_sales.groupby('warehouse_no')['qty'].sum().reset_index()
sales_groupby_product = df_sales.groupby('product_no')['qty'].sum().reset_index()
plt.figure(figsize=(10, 4))
plt.subplot(131)
plt.bar(sales_groupby_seller['seller_no'], sales_groupby_seller['qty'])
plt.xlabel('商家編碼')
plt.ylabel('銷售量')
plt.title('商家銷售量分布')
plt.subplot(132)
plt.bar(sales_groupby_warehouse['warehouse_no'], sales_groupby_warehouse['qty'])
plt.xlabel('倉庫編碼')
plt.ylabel('銷售量')
plt.title('倉庫銷售量分布')
plt.subplot(133)
plt.bar(sales_groupby_product['product_no'], sales_groupby_product['qty'])
plt.xlabel('商品編碼')
plt.ylabel('銷售量')
plt.title('商品銷售量分布')
plt.tight_layout()
plt.savefig('img/1.png',dpi=200)
plt.show()
商家數(shù)量: 35
倉庫數(shù)量: 54
商品數(shù)量: 1212
(2)特征工程
# 統(tǒng)計每個商家在每個倉庫每個商品中每天的平均銷量、總銷量等信息
sales_agg = df_sales.groupby(['seller_no','product_no', 'warehouse_no', 'date']).agg({
'qty': ['mean', 'sum']
}).reset_index()
sales_agg.columns = ['seller_no','product_no','warehouse_no', 'date', 'avg_qty', 'total_qty']
# # 構建時間窗口特征
sales_agg['rolling_mean_7d'] = sales_agg.groupby(['seller_no','product_no','warehouse_no'])['total_qty'].rolling(7).mean().reset_index(2, drop=True).reset_index()['total_qty']
sales_agg['rolling_mean_30d'] = sales_agg.groupby(['seller_no','product_no', 'warehouse_no'])['total_qty'].rolling(30).mean().reset_index(2, drop=True).reset_index()['total_qty']
sales_agg['rolling_std_30d'] = sales_agg.groupby(['seller_no','product_no', 'warehouse_no'])['total_qty'].rolling(7).std().reset_index(2, drop=True).reset_index()['total_qty']
sales_agg
(3)時間序列預測
店鋪、商品、倉庫對應的每一個時間序列,都要建立一個模型
from statsmodels.tsa.arima.model import ARIMA
df = sales_agg
# 選取一個seller、產(chǎn)品、倉庫,每個都要計算一遍
seller_list = sales_agg['seller_no'].unique()
warehouse_list = sales_agg['warehouse_no'].unique()
product_list = sales_agg['product_no'].unique()
result_table1 = []
df1_grouped = sales_agg.groupby(['seller_no','product_no','warehouse_no'])
for (seller_no,product_no,warehouse_no), df1_group in df1_grouped:
# # 訓練模型
model = ARIMA(ts_data, order=(1, 1, 1)).fit()
# # 預測
predict = model.predict(start=len(ts_data)+1, end=len(ts_data)+15, dynamic=True)
# # 將預測值轉(zhuǎn)化成DataFrame并返回
result = pd.DataFrame(columns=['seller_no','product_no','warehouse_no','date','forecast_qty'])
result['seller_no'] = [seller_no]*15
result['product_no'] = [product_no]*15
result['warehouse_no'] = [warehouse_no]*15
result['date']= pd.date_range(start='2023-05-16', periods=15, freq='D')
result['forecast_qty'] = list(predict)
result_table1.append(result)
merged_df = pd.concat(result_table1, axis=0, ignore_index=True)
merged_df.to_excel('結(jié)果表/結(jié)果表1-預測結(jié)果表.xlsx',index=False)
(4)聚類分析
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.preprocessing import LabelEncoder
# 讀取商家歷史出貨量表
df_sales = pd.read_excel('附件表/附件1-商家歷史出貨量表.xlsx')
# 讀取商品信息表
df_product = pd.read_excel('附件表/附件2-商品信息表.xlsx')
# 讀取商家信息表
df_seller = pd.read_excel('附件表/附件3-商家信息表.xlsx')
# 讀取倉庫信息表
df_warehouse = pd.read_excel('附件表/附件4-倉庫信息表.xlsx')
# 將日期轉(zhuǎn)換為時間序列
df_sales['date'] = pd.to_datetime(df_sales['date'])
# 合并商家歷史出貨量表和商品信息表
df_merge = df_sales.merge(df_product, on='product_no')
# 合并商家歷史出貨量表、商品信息表和商家信息表
df_merge = df_merge.merge(df_seller, on='seller_no')
# 合并商家歷史出貨量表、商品信息表、商家信息表和倉庫信息表
df_merge = df_merge.merge(df_warehouse, on='warehouse_no')
# 選擇需要的特征列
df_feature = df_merge[['seller_no', 'product_no', 'warehouse_no', 'category1', 'category2', 'category3', 'seller_category','inventory_category', 'seller_level', 'warehouse_category', 'warehouse_region', 'qty']]
# 對分類特征進行編碼
# 創(chuàng)建LabelEncoder對象
label_encoder = LabelEncoder()
# 需要進行數(shù)值編碼的列名
cat_cols = ['category1', 'category2', 'category3', 'seller_category','inventory_category', 'seller_level', 'warehouse_category', 'warehouse_region']
# 循環(huán)對每個類別特征進行數(shù)值編碼
for col in cat_cols:
df_feature[col] = label_encoder.fit_transform(df_feature[col])
df_feature
# 對數(shù)值特征進行歸一化
from sklearn.preprocessing import MinMaxScaler
# 創(chuàng)建MinMaxScaler對象
scaler = MinMaxScaler()
df_feature_2 = df_feature.drop(columns=['seller_no','product_no','warehouse_no'])
# 對df_feature進行歸一化
df_feature_normalized = pd.DataFrame(scaler.fit_transform(df_feature_2), columns=df_feature_2.columns)
df_feature_normalized
選擇最佳的聚類K值和隨機種子
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# 創(chuàng)建一個空列表存儲不同K值下的SSE得分
sse_scores = []
# 定義待測試的K值范圍
k_values = range(2, 10)
# 定義最佳的K值和隨機種子變量
best_k = 0
best_random_state = 0
best_sse = float('inf') # 初始值設為正無窮大
# 循環(huán)測試不同的K值和隨機種子
for k in k_values:
for random_state in range(10):
# 初始化KMeans模型
kmeans = KMeans(n_clusters=k, random_state=random_state)
# 訓練模型
kmeans.fit(df_feature_normalized)
# 計算SSE得分并存儲到列表中
sse = kmeans.inertia_
sse_scores.append((k, random_state, sse))
# 比較得分,更新最佳的K值和隨機種子
if sse < best_sse:
best_k = k
best_random_state = random_state
best_sse = sse
# 打印最佳的K值和隨機種子
print("最佳的K值:", best_k)
print("最佳的隨機種子:", best_random_state)
最佳的K值: 3
最佳的隨機種子: 7
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
best_k = 3
best_random_state = 7
# 可視化最佳K值和隨機種子下的聚類結(jié)果
kmeans_best = KMeans(n_clusters=best_k, random_state=best_random_state)
kmeans_best.fit(df_feature_normalized)
labels = kmeans_best.labels_
# 使用PCA將數(shù)據(jù)降至3維
pca = PCA(n_components=3)
df_feature_3d = pca.fit_transform(df_feature_normalized)
# 可視化最佳K值和隨機種子下的聚類結(jié)果
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(df_feature_3d[:, 0], df_feature_3d[:, 1], df_feature_3d[:, 2], c=labels, cmap='viridis')
ax.set_title('Clustering Result (K={}, Random State={})'.format(best_k, best_random_state))
plt.savefig('img/2.png',dpi=300)
plt.show()
根據(jù)以上的聚類效果,建議再進一步數(shù)據(jù)分析每個簇的數(shù)據(jù),具有哪些共同特征,然后反饋得到結(jié)論。
3.2 問題二
遍歷附件5的序列數(shù)據(jù),在附件1中查找相似的序列數(shù)據(jù),這里采用的歐式距離,建議其他相似度計算方式。
實現(xiàn)原理是,通過groupby方法,將附件5和附件1 的數(shù)據(jù)分組,得到時間序列數(shù)據(jù),只要在附件1中找到最相似的時間序列,就用此序列來訓練模型,以此來預測未來的數(shù)據(jù),作為附件5的預測結(jié)果。因為附件5中只有33個樣本,是不足以拿來直接訓練模型的,而附件1中又166個樣本,訓練的模型更可靠。算是一種模糊預測。
注意在計算歐式距離時,需要兩個序列長度是一樣的,那就取附件1中的倒數(shù)的數(shù)據(jù)和附件5中的數(shù)據(jù)對齊,意思是都是選擇最新的數(shù)據(jù)對其來計算相似度。
import pandas as pd
import numpy as np
from scipy.spatial.distance import cdist
from statsmodels.tsa.arima.model import ARIMA
from scipy.spatial.distance import euclidean
import warnings
warnings.filterwarnings('ignore')
# 讀取附件1和附件5的數(shù)據(jù)
df1 = pd.read_excel('附件表/附件1-商家歷史出貨量表.xlsx')
df5 = pd.read_excel('附件表/附件5-新品歷史出貨量表.xlsx')
# 整理成合適的數(shù)據(jù)格式,使用Pandas的DataFrame
df1['date'] = pd.to_datetime(df1['date'])
df1 = df1.sort_values('date')
df5['date'] = pd.to_datetime(df5['date'])
df5 = df5.sort_values('date')
# 根據(jù)附件5中的新維度,在附件1的數(shù)據(jù)中找到相似的歷史序列
# 對df1按照seller_no、warehouse_no、product_no分組,得到每個組內(nèi)的數(shù)據(jù)。
# 類似pivot table,但是pivot table之后需要reset_index,但是groupby不用,因此groupby更方便
df1_grouped = df1.groupby(['seller_no', 'warehouse_no', 'product_no'])
# 對df5按照seller_no、warehouse_no、product_no進行groupby
df5_grouped = df5.groupby(['seller_no', 'warehouse_no', 'product_no'])
# 計算每一個df5的序列與df1的每一個序列的距離,選擇最小距離的序列作為匹配的序列
result = []
i = 0
for (seller_no, warehouse_no, product_no), df5_group in df5_grouped:
min_distance = float('inf') # 初始化最小距離為無窮大
matched_sequence = None # 初始化匹配的序列為None
for (s1, w1, p1), df1_group in df1_grouped:
seq1 = list(df5_group['qty'])
seq2 = list(df1_group['qty'])
# 向前補充0使得seq1和seq2的長度相同
if len(seq1) < len(seq2):
seq2 = seq2[-len(seq1):]
elif len(seq1) > len(seq2):
seq1 = seq1[-len(seq2):]
distance = euclidean(seq1,seq2)# 計算距離
if distance < min_distance:
min_distance = distance
matched_sequence = (s1, w1, p1,seller_no, warehouse_no, product_no)
result.append(matched_sequence)
# 將結(jié)果輸出到DataFrame中
result_df = pd.DataFrame(result, columns=['seller_no_df1', 'warehouse_no_df1', 'product_no_df1', 'seller_no_df5', 'warehouse_no_df5', 'product_no_df5'])
result_df.to_excel('結(jié)果表/問題2-相似序列表.xlsx',index=False)
print(result_df.head())
根據(jù)相似的序列來建模并預測,作為附件5的預測結(jié)果
# 進行預測
from statsmodels.tsa.arima.model import ARIMA
df1 = pd.read_excel('附件表/附件1-商家歷史出貨量表.xlsx')
df5 = pd.read_excel('附件表/附件5-新品歷史出貨量表.xlsx')
result_df = result_df.drop_duplicates(subset=['seller_no_df5', 'warehouse_no_df5', 'product_no_df5'])
result_table2 = []
for index, row in result_df.iterrows():
seller_no, warehouse_no,product_no, seller_no_df5, product_no_df5, warehouse_no_df5 = row
# 類別銷售數(shù)據(jù)按照日期排序
ts_data = df1[(df1['seller_no'] == seller_no)& (df1['product_no'] == product_no) & (df1['warehouse_no'] == warehouse_no)][['date', 'qty']]
if len(ts_data)>0:
ts_data = ts_data.sort_values('date')
ts_data = ts_data.set_index('date')
# # 訓練模型
model = ARIMA(ts_data, order=(1, 1, 1)).fit()
# # 預測
predict = model.predict(start=len(ts_data)+1, end=len(ts_data)+15, dynamic=True)
# # # 將預測值轉(zhuǎn)化成DataFrame并返回
result = pd.DataFrame(columns=['seller_no','product_no','warehouse_no','date','forecast_qty'])
result['seller_no'] = [seller_no_df5]*15
result['product_no'] = [product_no_df5]*15
result['warehouse_no'] = [warehouse_no_df5]*15
result['date']= pd.date_range(start='2023-05-16', periods=15, freq='D')
result['forecast_qty'] = list(predict)
result_table2.append(result)
保存為提交結(jié)果
pd.concat(result_table2, axis=0, ignore_index=True).to_excel('結(jié)果表/結(jié)果表2-預測結(jié)果表.xlsx', index=False)
3.3 問題三
請下載完整代碼文章來源:http://www.zghlxwxcb.cn/news/detail-721223.html
4 下載方式
文章來源地址http://www.zghlxwxcb.cn/news/detail-721223.html
到了這里,關于【2023Mathorcup大數(shù)據(jù)】B題 電商零售商家需求預測及庫存優(yōu)化問題 python代碼解析的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!