1. 前期准备
引用相关库、设置程序运行路径
import os
os.chdir(r'C:\Users\86177\Desktop')
import warnings
warnings.filterwarnings('ignore')
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from bokeh.io import output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure,show
2. 数据加载及查看
1)数据导入及数据量大小查看
df = pd.read_excel('data.xlsx',index_col=0)
#df = pd.read_excel(r'data.xlsx')
#df.index = df['update_time']
print('数据量为{}条'.format(len(df)))
–> 输出结果为:(可以直接在读取数据的过程中就把某一列作为标签索引,也可以读取后再设定)
数据量为27642条
2) 查看数据标题名称和数据采集时间字段并提取采集日期
print([df.index.name] + df.columns.tolist())
print('数据的采集时段为:\n{}'.format(df.index.unique()))
df['date'] = df.index.day
print(df.isna().sum())
–> 输出结果为:(可以发现数据采集的时间是在11-5号至11月14,也就是在双十一的两周范围内,数据暂无缺失值)
['update_time', 'id', 'title', 'price', '店名', 'date']
数据的采集时段为:
DatetimeIndex(['2016-11-14', '2016-11-13', '2016-11-12', '2016-11-11',
'2016-11-10', '2016-11-09', '2016-11-08', '2016-11-07',
'2016-11-06', '2016-11-05'],
dtype='datetime64[ns]', name='update_time', freq=None)
id 0
title 0
price 0
店名 0
date 0
dtype: int64
3) 数据查看
print(df.head())
–> 输出结果为:
update_time id title price 店名 date
2016-11-14 A2251521828 相宜本草四倍多萃润泽精华保湿霜滋润面霜女补水 79.0 相宜本草 14
2016-11-14 A2251610120 正品相宜本草四倍多萃润泽洁面膏深层清洁滋润补水保湿 29.0 相宜本草 14
2016-11-14 A2251615486 相宜本草红石榴亮白嫩肤水女紧致补水保湿精华爽肤水女秋冬护肤品 108.0 相宜本草 14
2016-11-14 A2252191048 相宜本草红石榴鲜活透亮面贴膜7片补水保湿女化妆品滋润 79.0 相宜本草 14
2016-11-14 A2253094636 相宜本草去死皮膏洁净面部全身温和去角质补水化妆 35.0 相宜本草 14
3. 双十一当天在售的商品占比情况
1) 获得商品的销售的时间跨度
因为每个商品的id是相同的,上一部获取的商品的销售日期就是为了这一步提取具体的开售和停售的日期
d1 = df[['id','date']].groupby(by = 'id').agg(['min','max'])['date']
#d = df.groupby(by = 'id').agg(['min','max'])['date']
print(d1)
–> 输出结果为:(可以看看不加['date']
后的输出是什么)
2) 获取双十一在售商品的id并进行数据清洗
① 只要获取date字段中为11的id即可,注意这里可能存在相同的数据
id_11 = df[df['date'] == 11]['id']
print(id_11.is_unique)
–> 输出结果为:(可以发现的确存在相同的商品数据)
False
② 找到这个相同的数据
id_11 = data1[data1['date'] == 11]['id']
print(id_11.value_counts())
–> 输出结果为:(只有id为A37637194605的商品相同)
A37637194605 2
A540024035676 1
A522560429591 1
A527945447650 1
A521181542916 1
..
A526383253767 1
A40530583093 1
A529008131128 1
A520976852456 1
A528413776238 1
Name: id, Length: 2335, dtype: int64
③ 查看一下这个重复的数据是什么样子的
id_A37637194605 = df[df['id'].str.contains('A37637194605') & (df['date'] == 11)]
print(id_A37637194605)
–> 输出结果为:(根据输出发现,这两条数据是一样的,属于重复数据,可以直接删除)
update_time id title price 店名 date
2016-11-11 A37637194605 兰芝水衡致润保湿乳120ML 补水滋养长效保湿 亮肤控油 女 护肤 235.0 兰芝 11
2016-11-11 A37637194605 兰芝水衡致润保湿乳120ML 补水滋养长效保湿 亮肤控油 女 护肤 235.0 兰芝 11
④ 去除重复数据
id_11.drop_duplicates(inplace=True)
print(id_11.value_counts())
–> 输出结果为:(数据清洗完毕)
A540024035676 1
A536839755447 1
A527945447650 1
A521181542916 1
A540685584434 1
..
A526383253767 1
A40530583093 1
A529008131128 1
A520976852456 1
A528413776238 1
Name: id, Length: 2335, dtype: int64
★★★★★上面的判断是否有重复值、查看重复值、去除重复值,只是为了熟悉一下处理重复值的流程,熟练了之后可以直接使用如下的代码进行替换或者验证结果
id_11 = df[df['date'] == 11]['id'].unique()
m = len(d1)
m_11 = len(id_11)
m_pre = m_11/m
print("双十一当天参加活动的商品为{}个,占比为{:.2f}%".format(m_11, m_pre*100))
print('品牌总数为{}个\n'.format(len(data1['店名'].unique())),data1['店名'].unique())
–> 输出结果为:(与上面的Name: id
, Length: 2335
数据相符合,使用unique()
方法最后获得的naddary
数组,可以用来构建DataFrame
数据)
双十一当天参加活动的商品为2335个,占比为66.68%
品牌总数为22个
['相宜本草' '佰草集' '欧莱雅' '美宝莲' '玉兰油' '蜜丝佛陀' '悦诗风吟' 'SKII' '兰芝' '妮维雅' '自然堂' '倩碧'
'欧珀莱' '美加净' '雅诗兰黛' '资生堂' '兰蔻' '雅漾' '雪花秀' '植村秀' '薇姿' '娇兰']
4. 商品分类
1)获取双十一在售以及其他时段在售商品的信息
创建个d2
变量,用来保存统计的双十一在售的商品的情况,接着就可以和d1
按照商品的id
进行合并,得到完整的数据
d2 = pd.DataFrame({'id':id_11,'sale': True})
id_data = pd.merge(d1,d2,left_index = True, right_on = 'id',how = 'left').set_index(np.arange(len(d1)))
id_data.index.name = 'index'
id_data.fillna(False,inplace=True)
print(id_data.head(15))
–> 输出结果为:(以d1
为依据进行的合并,必然就会有缺失值,这里是以False
进行填充,顺带进行重新设置标签及标签名称)
2)商品分类
按照商品销售节奏分类,可以将商品分为7类
A. 11.11前后及当天都在售 → 一直在售
B. 11.11之后停止销售 → 双十一后停止销售
C. 11.11开始销售并当天不停止 → 双十一当天上架并持续在售
D. 11.11开始销售且当天停止 → 仅双十一当天有售
E. 11.5 - 11.10 → 双十一前停止销售
F. 仅11.11当天停止销售 → 仅双十一当天停止销售
G. 11.12开始销售 → 双十一后上架
① 商品类别划分
id_data['type'] = '待分类'
id_data['type'][(id_data['min'] < 11) & (id_data['max'] >11) & (id_data['sale'] == True)] = 'A'
id_data['type'][(id_data['min'] < 11) & (id_data['max'] ==11)] = 'B'
id_data['type'][(id_data['min'] == 11) & (id_data['max'] >11)] = 'C'
id_data['type'][(id_data['min'] == 11) & (id_data['max'] ==11)] = 'D'
id_data['type'][(id_data['max'] < 11)] = 'E'
id_data['type'][(id_data['min'] < 11) & (id_data['max'] >11) & (id_data['sale'] == False)] = 'F'
id_data['type'][(id_data['min'] > 11)] = 'G'
print(id_data.head(5))
print(id_data.tail(5))
–> 输出结果为:(划分之前要创建一个空字段,可以输入任意的数据,之后进行填充数据,也就是进行简单的逻辑判断)
min max id sale type
index
0 5 14 A10027317366 True A
1 5 14 A10588608182 True A
2 5 14 A10847151685 True A
3 5 10 A12229499633 False E
4 5 11 A12229615671 True B
min max id sale type
index
3497 5 14 A9555524581 True A
3498 5 11 A9609851200 True B
3499 7 14 A9703525117 True A
3500 5 14 A9709829810 True A
3501 5 14 A9768255247 True A
② 各类商品统计
result1 = id_data['type'].value_counts()
print(result1)
–> 输出结果为:
A 1820
E 841
B 458
F 242
G 84
C 39
D 18
Name: type, dtype: int64
③ 绘制饼图
需要注意的是,最后三个类别的占比都是比较小的,在绘制饼图的时候应该有意识的进行错开,而不是直接使用这个排序后的数据进行绘制
from bokeh.palettes import brewer
colori = brewer['YlGn'][7]
#设置颜色
result1 = result1.loc[['A','C','B','D','E','F','G']]# 重新调整排序
plt.pie(result1,labels = result1.index, autopct='%.2f%%',pctdistance=0.65,labeldistance =1.1,explode = [0,0,0,0,0.1,0,0],
startangle=90, shadow = True,radius=1.5,counterclock=False, colors = colori)
–> 输出结果为:(具体的设置可以根据需要进行微调)
5. 未参与双十一当天活动的商品,在双十一之后的去向如何?
这里按照四个condition
进行考虑,主要是处理E、F中的数据
con1 → 暂时下架(F)
con2 → 重新上架(E中部分数据,数据中同一个id可能有不同title,“换个马甲重新上架”)
con3 → 预售(E中部分数据,预售商品的title中包含“预售”二字),字符串查找特定字符 df.str.contains(‘预售’)
con4 → 彻底下架(E中部分数据),可忽略
1)找到未参与双十一当天活动的商品id并筛选出原始数据
id_not11 = id_data[id_data['sale']==False] # 筛选出双十一当天没参加活动的产品id
print('双十一当天没参加活动的商品总数为{}个,占比为{:.2f}%\n-------'.format(len(id_not11),len(id_not11)/m*100))
print('双十一当天没参加活动的商品销售节奏类别为:\n',id_not11['type'].value_counts().index.tolist())
–> 输出结果为:(其中G
类商品只是满足双十一之后销售,但是双十一之前并没有销售,所以G
类商品不在这次的处理之内,也就是上面说的主要处理E
、F
类数据)
双十一当天没参加活动的商品总数为1167个,占比为33.32%
-------
双十一当天没参加活动的商品销售节奏类别为:
['E', 'F', 'G']
筛选出未参与双十一当天活动商品id
对应的原始数据
df_not11 = id_not11[['id','type']]
data_not11 = pd.merge(df_not11,df,on = 'id', how = 'left')
print(data_not11.head(15))
–> 输出结果为:
2) 筛选出con1
的商品数据
就是筛选处F
类商品的数据即可
id_con1 = id_data['id'][id_data['type'] == 'F'].values
3) 筛选出con2
的商品数据
data_con2 = data_not11[['id','title','date']].groupby(by = ['id','title']).count()
title_count = data_con2.reset_index()['id'].value_counts()
id_con2 = title_count[title_count>1].index
–> 输出结果为:(按照id
和title
字段进行数据的汇总,这样就会保留一个id
对应多个title
的商品数据了,然后在对id
字段进行统计长度就知道con2
条件下的商品数量了)
4) 筛选出con3
的商品数据
data_con3 = data_not11[data_not11['title'].str.contains('预售')]
id_con3 = data_con3['id'].value_counts().index
5) 输出三种condition
下的商品情况
print("未参与双十一当天活动的商品中:\n暂时下架商品的数量为{}个,重新上架商品的数据量为{}个,预售商品的数据量为{}个"
.format(len(id_con1), len(id_con2), len(id_con3)))
–> 输出结果为:
未参与双十一当天活动的商品中:
暂时下架商品的数量为242个,重新上架商品的数据量为110个,预售商品的数据量为453个