一、比赛简介
在本次比赛中,您将使用具有挑战性的时间序列数据集,其中包括每日销售数据,该数据集由俄罗斯最大的软件公司之一-1C Company提供。
我们要求您预测下个月每个产品和商店的总销售额。通过解决这一竞争,您将能够应用和增强您的数据科学技能。
系统会为您提供每日历史销售数据。任务是预测测试集在每个商店中出售的产品总数。请注意,商店和产品清单每个月都会略有变化。创建可以处理此类情况的可靠模型是挑战的一部分。
二、数据分析1
数据集简介
- sales_train.csv-训练集。2013年1月至2015年10月的每日历史数据。
- test.csv-测试集。您需要预测这些商店和产品在2015年11月的销售额。
- sample_submission.csv-正确格式的示例提交文件。
- items.csv-有关项目/产品的补充信息。
- item_categories.csv- 有关项目类别的补充信息。
- shop.csv-有关商店的补充信息。
属性简介
- ID- 代表测试集中的(商店,商品)元组的ID
- shop_id-商店的唯一标识符
- item_id-产品的唯一标识符
- item_category_id-项目类别的唯一标识符
- item_cnt_day-销售的产品数量。您正在预测该指标的每月金额
- item_price-商品的当前价格
- 日期 -格式为dd / mm / yyyy的日期
- date_block_num-连续的月份号,为方便起见。2013年1月为0,2013年2月为1,...,2015年10月为33
- item_name- 项目名称
- shop_name-商店名称
- item_category_name-项目类别名称
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
利用pandas分析数据,可以发现没用空值和缺失值等
sale_train = pd.read_csv('data/data45414/sales_train.csv')
print("----------前五行数据----------")
print(sale_train.head(5))
print("-----------数据信息-----------")
print(sale_train.info())
print("-----------数据类型-----------")
print(sale_train.dtypes)
print("----------缺失值-----------")
print(sale_train.isnull().sum())
print("----------空值-----------")
print(sale_train.isna().sum())
print("----------数据集大小----------")
print(sale_train.shape)
----------前五行数据----------
date date_block_num shop_id item_id item_price item_cnt_day
0 02.01.2013 0 59 22154 999.00 1.0
1 03.01.2013 0 25 2552 899.00 1.0
2 05.01.2013 0 25 2552 899.00 -1.0
3 06.01.2013 0 25 2554 1709.05 1.0
4 15.01.2013 0 25 2555 1099.00 1.0
-----------数据信息-----------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2935849 entries, 0 to 2935848
Data columns (total 6 columns):
date object
date_block_num int64
shop_id int64
item_id int64
item_price float64
item_cnt_day float64
dtypes: float64(2), int64(3), object(1)
memory usage: 134.4+ MB
None
-----------数据类型-----------
date object
date_block_num int64
shop_id int64
item_id int64
item_price float64
item_cnt_day float64
dtype: object
----------缺失值-----------
date 0
date_block_num 0
shop_id 0
item_id 0
item_price 0
item_cnt_day 0
dtype: int64
----------空值-----------
date 0
date_block_num 0
shop_id 0
item_id 0
item_price 0
item_cnt_day 0
dtype: int64
----------数据集大小----------
(2935849, 6)
我们可以发现存在之重复值,但是只有6行,因此是否进行处理对整体的数据并无太大影响
print('重复数量:', len(sale_train[sale_train.duplicated()]))
重复数量: 6
接下来可以对数据类型进行修改,减小数据集的大小
def downcast_dtypes(df):
float_cols = [c for c in df if df[c].dtype == "float64"] # 取得类型为float64的类别
int_cols = [c for c in df if df[c].dtype in ["int64", "int32"]] # 取得类型为int64和32的类别
df[float_cols] = df[float_cols].astype(np.float32)
df[int_cols] = df[int_cols].astype(np.int16)
return df
sale_train = downcast_dtypes(sale_train)
print(sale_train.info())
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2935849 entries, 0 to 2935848
Data columns (total 6 columns):
date object
date_block_num int16
shop_id int16
item_id int16
item_price float32
item_cnt_day float32
dtypes: float32(2), int16(3), object(1)
memory usage: 61.6+ MB
None
根据item_id查看数据,并画图
sales_by_item_id = sale_train.pivot_table(index=['item_id'],values=['item_cnt_day'],
columns='date_block_num', aggfunc=np.sum, fill_value=0).reset_index() # item_id为第一列标签,date_block_num为行标签,对同一个item_id的item_cnt_day求和,并且空值填充为0,最后重置索引
# print(sales_by_item_id.head(5))
sales_by_item_id.columns = sales_by_item_id.columns.droplevel().map(str) # 去掉字符索引
# print(sales_by_item_id.head(5))
sales_by_item_id = sales_by_item_id.reset_index(drop=True).rename_axis(None, axis=1) # 去掉字符索引
# print(sales_by_item_id.head(5))
sales_by_item_id.columns.values[0] = 'item_id' # 填充字符标志
item_id 0 1 2 3 4 5 6 7 8 ... 24 25 26 27 28 29 30 31 32
0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
2 2 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
3 3 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
4 4 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0
33
0 0
1 0
2 0
3 0
4 0
[5 rows x 35 columns]
print(sales_by_item_id.head(5))
print(sales_by_item_id.sum()[1:])
sales_by_item_id.sum()[1:].plot(legend=True, label="Monthly sum") # 各月份所有货物总和
print(sales_by_item_id.mean()[1:])
sales_by_item_id.mean()[1:].plot(legend=True, label="Monthly mean") # 月平均
0 131479
1 128090
2 147142
3 107190
4 106970
5 125381
6 116966
7 125291
8 133332
9 127541
10 130009
11 183342
12 116899
13 109687
14 115297
15 96556
16 97790
17 97429
18 91280
19 102721
20 99208
21 107422
22 117845
23 168755
24 110971
25 84198
26 82014
27 77827
28 72295
29 64114
30 63187
31 66079
32 72843
33 71056
dtype: int64
0 6.029211
1 5.873802
2 6.747466
3 4.915394
4 4.905306
5 5.749576
6 5.363691
7 5.745449
8 6.114184
9 5.848627
10 5.961801
11 8.407484
12 5.360618
13 5.029899
14 5.287156
15 4.427753
16 4.484340
17 4.467786
18 4.185812
19 4.710460
20 4.549365
21 4.926033
22 5.403999
23 7.738570
24 5.088779
25 3.861054
26 3.760902
27 3.568900
28 3.315220
29 2.940065
30 2.897556
31 3.030174
32 3.340349
33 3.258403
dtype: float64
查看有多少货物在6个月内无销量
outdated_items = sales_by_item_id[sales_by_item_id.loc[:,'27':].sum(axis=1)==0]
print('过时:', len(outdated_items))
过时: 12391
查看测试集中过时货物占多少
test = pd.read_csv('data/data45414/test.csv')
print('测试集中的过时货物:', len(test[test['item_id'].isin(outdated_items['item_id'])]))
测试集中的过时货物: 6888
查看销售量和销售价格中的异常值
plt.figure(figsize=(10,4))
plt.xlim(-100, 3000)
sns.boxplot(x=sale_train['item_cnt_day'])
print('Sale volume outliers:',sale_train['item_id'][sale_train['item_cnt_day']>500].unique())
plt.figure(figsize=(10,4))
plt.xlim(sale_train['item_price'].min(), sale_train['item_price'].max())
sns.boxplot(x=sale_train['item_price'])
print('Item price outliers:',sale_train['item_id'][sale_train['item_price']>50000].unique())
Sale volume outliers: [ 8057 20949 9242 19437 3731 11373 9249 9248]
Item price outliers: [11365 6066 13199]
可能的item_id特征:
- 滞后性
- 销售日期
- 上月销售量
- 打折日期
- 相关的数据
根据shop_id查看数据
根据商店分类数据,可能存在新店有高峰值,6个月无销售量的店可能关门了
sales_by_shop_id = sale_train.pivot_table(index=['shop_id'],values=['item_cnt_day'],
columns='date_block_num', aggfunc=np.sum, fill_value=0).reset_index()
sales_by_shop_id.columns = sales_by_shop_id.columns.droplevel().map(str)
sales_by_shop_id = sales_by_shop_id.reset_index(drop=True).rename_axis(None, axis=1)
sales_by_shop_id.columns.values[0] = 'shop_id'
for i in range(6,34):
print('Not exists in month',i,sales_by_shop_id['shop_id'][sales_by_shop_id.loc[:,'0':str(i)].sum(axis=1)==0].unique())
for i in range(6,28):
print('Shop is outdated for month',i,sales_by_shop_id['shop_id'][sales_by_shop_id.loc[:,str(i):].sum(axis=1)==0].unique())
Not exists in month 6 [ 9 11 20 33 34 36 39 40 48 49]
Not exists in month 7 [ 9 11 20 33 34 36 39 40 48 49]
Not exists in month 8 [ 9 11 20 33 34 36 39 40 48 49]
Not exists in month 9 [11 20 33 34 36 39 40 48 49]
Not exists in month 10 [11 20 33 34 36 39 40 48 49]
Not exists in month 11 [11 20 33 34 36 39 40 48]
Not exists in month 12 [11 20 33 34 36 39 40 48]
Not exists in month 13 [11 20 33 34 36 39 40 48]
Not exists in month 14 [11 20 33 34 36 48]
Not exists in month 15 [11 20 33 34 36]
Not exists in month 16 [11 20 33 34 36]
Not exists in month 17 [11 20 33 34 36]
Not exists in month 18 [11 20 33 36]
Not exists in month 19 [11 20 36]
Not exists in month 20 [11 20 36]
Not exists in month 21 [11 36]
Not exists in month 22 [11 36]
Not exists in month 23 [11 36]
Not exists in month 24 [