Python 数据分析微专业课程--项目07 电商打折套路解析

1.项目说明

基于双十一淘宝美妆数据分析双十一期间各品牌化妆品的销售情况及打折情况,并分析个品牌化妆品的打折特点,分析其套路。

2.项目具体要求

1、从双十一淘宝美妆数据,分析出“各个品牌都有多少商品参加了双十一活动?”
要求:
① 计算得到:商品总数、品牌总数
② 双十一当天在售的商品占比情况
③ 真正参与双十一活动的品牌有哪些?其各个品牌参与双十一活动的商品数量分布是怎样的?

2、哪些商品真的在打折呢?
要求:
① 针对每个商品,评估其打折的情况
② 针对在打折的商品,其折扣率是多少
③ 按照品牌分析,不同品牌的打折力度

3、商家营销套路挖掘?
要求:
① 解析出不同品牌的参与打折商品比例及折扣力度,并做散点图,总结打折套路

3.实现思路:

1.”双十一淘宝美妆数据”是各个品牌在11/5~11/14期间每天在售的商品及价格情况,各个商品在双十一及其前后的有以下几种情况:
A. 11.11前后及当天都在售 → 一直在售
B. 11.11之后停止销售 → 双十一后停止销售
C. 11.11开始销售并当天不停止 → 双十一当天上架并持续在售
D. 11.11开始销售且当天停止 → 仅双十一当天有售
E. 11.5 - 11.10 → 双十一前停止销售
F. 仅11.11当天停止销售 → 仅双十一当天停止销售
G. 11.12开始销售 → 双十一后上架
根据每种商品的销售情况将商品分类,追加类别字段,然后可以根据要求分组统计商品总数,品牌总数,双十一当天商品数量,以及
每个销售类别的商品的数量,绘制饼图来查看各个类别商品数量的分布情况。
真正参与双十一活动的商品:双十一当天在售的商品 + 预售商品,可以分别计算每个品牌的双十一在售和预售商品,绘制柱状堆叠图。

2.分析商品的打折情况和折扣率可以首先判断是否有打折,然后计算折扣率 = 双十一当天价格 / 双十一之前价格,
将数据分为’双11之前’,’双11’,’双11之后’三个时间段,根据不同时间段的价格波动情况,判断商品打折情况,然后计算每个商品的打折率,
分析打折情况和力度可以分析不同的折扣区间的商品数量,绘制折线图,看不同折扣区间的商品折扣数量变化情况;
按品牌分析可以绘制散点图,看不同品牌商品的折扣分布情况,这里可以使用bokeh来实现,设置十字线和标签显示。

3.最后分析电商打折套路,实际上是分析各个品牌电商参与打折商品的数量以及折扣情况的特点,这里可以划分为四个特征:
a.少量商品少打折
b.少量商品大打折
c.大量商品少打折
d.大量商品大打折
因此可以绘制散点图,将图形根据均值划分为四个对应象限,就可以清楚直观的得到各个品牌的打折套路了

4.实现过程:

import numpy as np
import pandas as pd 
import matplotlib.pyplot as plt


import warnings
warnings.filterwarnings('ignore') 
# 不发出警告

from bokeh.io import output_notebook
output_notebook()
# 导入notebook绘图模块

from bokeh.plotting import figure,show
from bokeh.models import ColumnDataSource
# 导入图表绘制、图标展示模块
# 导入ColumnDataSource模块

data = pd.read_excel(r'D:\IT\python数据分析师\项目8\双十一淘宝美妆数据.xlsx') 
#读取淘宝美妆excel表格数据

data['date'] = data['update_time'].apply(lambda x:x.day) #获取update_time的day,生成单独列

commodity_ttl = data[['id']].drop_duplicates().count()  #商品总数
brand_ttl = data[['店名']].drop_duplicates().count()  #品牌总数
commodity_on11 = data.loc[data['date']==11,['id']].drop_duplicates().count() #双11在售商品数量
print('商品总数为:%i' % commodity_ttl) 
print('品牌总数为:%i' % brand_ttl)
print('双十一当天在售商品占比情况: %.2f' % (commodity_on11/commodity_ttl))    #打印双11在售的商品占比情况


data1 = data.groupby('id')['date'].agg({'min':np.min,'max':np.max}) 
data2 = data[data['date']==11][['id','date']].set_index('id').rename(columns = {'date':'date_11'})
data1 = data1.join(data2).fillna(0)

data1.loc[((data1['min']<11)&(data1['max']>11)&(data1['date_11']==11)),'class']='A'
data1.loc[((data1['min']<11)&(data1['max']==11)),'class']='B'
data1.loc[((data1['min']==11)&(data1['max']>11)),'class']='C'
data1.loc[((data1['min']==11)&(data1['max']==11)),'class']='D'
data1.loc[((data1['min']<11)&(data1['max']<11)),'class']='E'
data1.loc[((data1['min']<11)&(data1['max']>11)&(data1['date_11']==0)),'class']='F'
data1.loc[((data1['min']>11)&(data1['max']>11)),'class']='G'
#根据商品销售节奏将商品分成7类
#A. 11.11前后及当天都在售 → 一直在售
#B. 11.11之后停止销售 → 双十一后停止销售
#C. 11.11开始销售并当天不停止 → 双十一当天上架并持续在售
#D. 11.11开始销售且当天停止 → 仅双十一当天有售
#E. 11.5 - 11.10 → 双十一前停止销售
#F. 仅11.11当天停止销售 → 仅双十一当天停止销售
#G. 11.12开始销售 → 双十一后上架

print(data1.head())

#根据商品分类的数量占比绘制饼图
data_class = pd.merge(data,data1[['class']],how='outer',left_on = 'id',right_index= True)[['update_time','id','title','店名','class']]
data_r = data_class[['id','class']].drop_duplicates().groupby(by ='class').size()
#饼图数据

colors =plt.cm.PuBu_r(np.linspace(0,0.7,7))
#颜色设置

plt.axis('equal')
plt.pie(data_r,colors = colors,autopct='%.2f%%',pctdistance=0.8,labels= data_r.index,radius= 2,
    startangle = -90,textprops={'fontsize':15,'color':'k'})

print(data_r)
#饼图绘制

说明:
1.对日期字段取’day’作为新建新的’date’字段,每个商品数据中有等于11说明在双11当天有售,计算出双11当天在售商品占比为:67%。这说明有超过30%的商品只是借助双11的热度在进行促销,并未真正参与双11当天活动。
2.根据每个商品date字段最大值和最小值与11进行比较,以及双十一当天是否在售来判断商品销售节奏的类型,分别筛选并添加类型字段, 然后根据类型字段分组求数量,使用该数据绘制饼图,可以清晰的查看每个类型的占比情况。
3.根据占比情况可知,正常一直在售并参与双11打折活动的商品占比只有50%左右,其余的商品双十一前停止销售的占24%,双11之后停止销售的占13%,仅11.11当天停止销售的占7%,其他的为占比较小的其他类型,说明双11活动期间的商品销售节奏类型多样,并非仅仅是是否打折或者折扣多少不同, 有超过一般的商品使用各种方式在双11期间进行销售。

from bokeh.core.properties import value

#真正参加活动的商品 = 双十一当天在售的商品 + 预售商品 
data_ys = data_class[data_class['title'].str.contains('预售')]  # 预售商品数据
data_on11 = data_class[data_class['class'].isin(['A','B','C','D'])] #双11当天在售的商品
data_hd = pd.concat([data_ys,data_on11],join = 'inner').drop_duplicates() 
#连接预售和双11在售数据去重得到所有真正参加活动的商品

data_hd = data_hd[['id','店名','class']].drop_duplicates() 
sale_on_11 =data_hd[data_hd['class'].isin(['A','B','C','D'])] # 双11在售商品id,品牌数据
presell =data_hd[~data_hd['class'].isin(['A','B','C','D'])] #双11当天未销售,但是有预售的id,品牌数据

sale_on_11 = sale_on_11.groupby('店名')[['id']].count().rename(columns ={'id':'sale_on_11'}) #双11在售商品各个品牌商品总数
presell = presell.groupby('店名')[['id']].count().rename(columns = {'id':'presell'})#双11当天未销售,但是有预售各个品牌商品总数
brand_hd = sale_on_11.join(presell,how = 'left') 

brand_hd['total'] = brand_hd['sale_on_11']+ brand_hd['presell']  #各个品牌参与活动商品总数
brand_hd = brand_hd.sort_values(by = 'total',ascending= False)[['sale_on_11','presell']] #根据总数排序


source = ColumnDataSource(data = brand_hd)  #生成数据

p = figure(x_range=brand_hd.index.tolist(),plot_width =900,plot_height=350, 
    title="各个品牌参与双十一活动的商品数量分布",toolbar_location = 'right')
#生成绘图对象,设置x_range 为品牌名称

renderers = p.vbar_stack(brand_hd.columns.tolist(), 
                x='店名',     
                 source=source,
                width=0.9, color=['mediumpurple','olive'],
                legend = [value(x) for x in brand_hd.columns.tolist()])
#绘制柱状堆叠图

p.xgrid.grid_line_color = None  
p.yaxis.minor_tick_line_color = None
p.outline_line_color = None
p.legend.orientation = 'horizontal'

show(p)

说明:
1.这里计算各品牌真正参与双十一打折活动的商品数量情况,真正参加活动的商品 = 双十一当天在售的商品 + 预售商品 。
2.分别筛选出双十一当天在售的商品数据和预售商品数据,然后进行数据连接,去除重复数据后就得到真正参与活动商品的数据。
3.然后使用bokeh绘制堆叠柱状图,根据柱状图可知各个品牌参与活动商品数量情况。

#将数据分为'双11之前','双11','双11之后'三个时间段,根据不同时间段的价格波动情况,判断商品打折的情况
#计算商品的折扣率情况和不同品牌的打折情况
#折扣率 = 双十一当天价格 / 双十一之前价格
delta = data['update_time'] - pd.to_datetime('2016-11-11')  #距离双11的日期差
delta = delta.apply(lambda x:int(x.days))   #获得日期差的数值
data['cut_11'] = pd.cut(delta,bins = [-7,-1,0,3],labels=['双11之前','双11','双11之后'])
# pd.cut() 将数据划分为'双11之前','双11','双11之后'

data_dz = data[['id','price','cut_11','店名']].groupby(['id','cut_11']).min()
#根据商品和时间段分组,获得各个区间段内的最小价格数据

data_before = data_dz.loc[(slice(None),'双11之前'),:].reset_index()[['id','price','店名']]  #双11之前的价格
data_on11 = data_dz.loc[(slice(None),'双11'),:].reset_index()[['id','price','店名']]  #双11当天的价格
data_dz1 = pd.merge(data_before,data_on11,on='id',how = 'outer',suffixes=('_before','_on11')).dropna()
#连接数据

data_dz1['discount'] = data_dz1['price_on11']/data_dz1['price_before']  #获得每个商品的折扣率
data_dz2 = data_dz1[data_dz1['discount']<=0.95].sort_values(by='discount').reset_index(drop=True)
#清除折扣率大于0.95的商品,并根据折扣率排序

from bokeh.models import HoverTool
from bokeh.transform import jitter
#导入绘图模块



lst_dz = ['(0.0, 0.05]', '(0.05, 0.1]', '(0.1, 0.15]', '(0.15, 0.2]',
         '(0.2, 0.25]', '(0.25, 0.3]', '(0.3, 0.35]', '(0.35, 0.4]',
         '(0.4, 0.45]', '(0.45, 0.5]', '(0.5, 0.55]', '(0.55, 0.6]',
        '(0.6, 0.65]', '(0.65, 0.7]', '(0.7, 0.75]', '(0.75, 0.8]',
        '(0.8, 0.85]', '(0.85, 0.9]', '(0.9, 0.95]']
#x_range 数据

dz_count = pd.cut(data_dz2['discount'],np.arange(0,1,0.05)).value_counts().sort_index()
#打折区间划分

df_dz = pd.DataFrame(data = dz_count.values,index =lst_dz,columns = ['QTY']) #折扣率区间商品数量数据
df_dz['QTY_n'] = df_dz['QTY']/df_dz['QTY'].sum() #每个折扣率区间商品数量比例
df_dz.index.name = 'label'
df_dz.sort_index(inplace = True) #按折扣率区间大小排序

source = ColumnDataSource(data = df_dz)  #生成数据


hover = HoverTool(tooltips=[("折扣率", "@label"),("商品数量","@QTY")]) #悬浮数据显示设置


p = figure(x_range = lst_dz,plot_width = 800,plot_height = 300,toolbar_location = 'right',
        tools = [hover,'box_select,wheel_zoom,reset,crosshair'],title = '商品折扣率统计')

p.circle(x = 'label' ,y='QTY_n',source = source,
        size = 7,fill_color = 'red',alpha = 0.7)
#绘制折扣率点图

p.line(x = 'label',y='QTY_n',source = source,
     line_width = 1,line_color = 'black',line_dash=[6,3])
#绘制折扣率线图

p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
show(p)

#绘制品牌打折情况图表

brand_zkl = data_dz1[['店名_on11','discount']].rename(columns = {'店名_on11':'brand'}) 
brand_zkl = brand_zkl[brand_zkl['discount']<=0.95]
brand = brand_zkl['brand'].unique().tolist()
#筛选出品牌,以及商品折扣率数据

source = ColumnDataSource(data = brand_zkl)#生成数据

hover = HoverTool(tooltips = [("discount","@discount")])

p = figure(y_range = brand,plot_width = 800,plot_height =500,title = '不同品牌折扣率情况',
         tools = [hover,'wheel_zoom,reset,crosshair'])

p.circle(x = 'discount',y= jitter('brand',width = 0.3,range =p.y_range ),source = source,alpha = 0.6)
#绘制点图

p.ygrid.grid_line_color = None

show(p)

说明:
1.折扣率 = 双十一当天价格 / 双十一之前价格,因此将商品划分为’双11之前’,’双11’,’双11之后’三个时间段,筛选出双十一之前价格和双十一当天价格数据,即可计算出每种参与活动商品的折扣率数据。对于折扣率我们进行两方面分析,
第一:分析折扣率分布情况,可以统计每个折扣区间的商品数量,绘制折线图和散点图;
第二:分析每个品牌参与活动的商品折扣分布情况,以折扣和品牌为X,Y轴绘制散点图;
2.根据图表分析可知:
a.参加获得的品牌中,商品多的品牌并未有明显折扣,例如雅诗兰黛和悦丝风吟两个品牌,有折扣的商品很少,甚至没有。
b.有加大折扣的商品折扣率主要在0.45~0.5,较小折扣的商品折扣率只要在0.85~0.9,其他折扣率商品相对较少,主要在0.5~0.8区间。
c.各个品牌中折扣力度大且商品较多的品牌主要有相宜本草和佰草集两个品牌,且这两个品牌在各个折扣区间都有商品分布。其他品牌要么折扣率集中在0.9附近,要么在0.6~0.9之间进行均匀分布。

from bokeh.models.annotations import Span
from bokeh.models.annotations import BoxAnnotation
from bokeh.models.annotations import Label
#导入辅助线,矩形和注释模块

brand_ttl = data[['id','店名']].drop_duplicates().groupby('店名').count()  #各个品牌商品总数
brand_dz = data_dz1[data_dz1['discount']<1][['id','店名_on11']].groupby('店名_on11').count() #各个品牌打折商品总数
brand_zkld = data_dz1[data_dz1['discount']<1][['店名_on11','discount']].groupby('店名_on11').mean()#各个品牌折扣均值,就是折扣力度

brand_jx = brand_ttl.join(brand_dz,rsuffix='_dz').join(brand_zkld).dropna()#数据连接,获得品牌打折解析数据
brand_jx['ratio'] = brand_jx['id_dz']/brand_jx['id'] #品牌打折商品占比
brand_jx['size'] = brand_jx['id']*0.3 #用商品总数得到点大小数据
brand_jx.index.name = 'brand'

x_mean = brand_jx['ratio'].mean()  #打折商品比例均值
y_mean = brand_jx['discount'].mean() #商品占比均值

source = ColumnDataSource(data = brand_jx)  #生成数据

hover = HoverTool(tooltips = [("品牌",'@brand'),
                ("折扣率",'@discount'),
                ('商品总数','@id'),
                ('参与打折商品比例:',"@ratio")])
#悬浮显示数据设置

p = figure(plot_width = 600,plot_height = 600,title = '各个品牌打折套路解析',
        tools = [hover,'box_select,wheel_zoom,reset,crosshair'])
#生成绘图对象

p.circle(x='ratio',y='discount',source = source,size ='size',color = 'tomato',line_dash = [10,4],alpha = 0.6)
p.x(x='ratio',y='discount',source = source,size = 'size',color = 'black',alpha = 0.6,line_dash = [10,4])
#绘制点/X 

p.xgrid.grid_line_dash = [10,4]
p.ygrid.grid_line_dash = [10,4]

x = Span(location = x_mean,dimension = 'height',line_color = 'forestgreen',line_dash =[10,4],line_alpha = 0.7)
y = Span(location = y_mean,dimension = 'width',line_color = 'forestgreen',line_dash =[10,4],line_alpha = 0.7)
p.add_layout(x)
p.add_layout(y)
#绘制并添加均值线

qd1 = BoxAnnotation(bottom = y_mean,right = x_mean,fill_color = 'gold',fill_alpha = 0.1)
label1 = Label(x=x_mean-0.15,y = y_mean+0.1,text = '少量少打折',text_font_size = '12pt')
p.add_layout(qd1)
p.add_layout(label1)
#绘制‘少量少打折象限’

qd2 = BoxAnnotation(bottom = y_mean,left = x_mean,fill_color = 'red',fill_alpha = 0.1)
label2 = Label(x=x_mean+0.1,y = y_mean+0.1,text = '大量少打折',text_font_size = '12pt')
p.add_layout(qd2)
p.add_layout(label2)
#绘制‘大量少打折象限’

qd3 = BoxAnnotation(top = y_mean,right = x_mean,fill_color = 'red',fill_alpha = 0.1)
label3= Label(x=x_mean-0.15,y = y_mean-0.1,text = '少量大打折',text_font_size = '12pt')
p.add_layout(qd3)
p.add_layout(label3)
#绘制‘少量大打折象限’

qd4 = BoxAnnotation(top = y_mean,left = x_mean,fill_color = 'gold',fill_alpha = 0.1)
label4 = Label(x=x_mean+0.1,y = y_mean-0.1,text = '大量大打折',text_font_size = '12pt')
p.add_layout(qd4)
p.add_layout(label4)
#绘制‘大量大打折象限’

show(p)

说明:
1.以上分析中知道各个品牌的折扣率分布较为复杂,为分析每个品牌的打折套路,这里个根据均值将各个品牌根据折扣率和商品数量划分为四个象限,可以清楚地得到各个品牌的打折套路:
a.少量少打折:娇兰,兰蔻,玉兰油,欧兰雅
b.少量大打折:薇姿,悦丝风吟,欧珀莱,兰芝
c.大量少打折:美加净,妮维雅,美宝莲,蜜丝佛陀
d.大量大打折:自然堂,佰草集,相宜本草

5.总结

  • 该项目对数据清洗,筛选计算的要求较高,且bokeh绘图要求多且复杂,完成该项目对于使用pandas处理数据和bokeh绘图是一个很好的练习。
  • 该项目虽然只使用了点一部分化妆品的电商数据进行分析,且只是分析打折的套路,但是其完成思路对于分析销售数据非常实用。
  • 对于销售数据的分析有很多角度和统计量,数据量相对完整的情况下,可以在该项目分析思路的基础上进行发散,例如:
    a.可以分析各个品牌的一年中的电商销售情况,看双十一期间的销售是否有较大的增加,销售量与折扣率的关系如何;
    b.双十一中各个商品的促销手段和销售策略有什么不同,与销量的关系如何,哪种促销手段和策略最为有效;
    c.根据双十一期间商品数据可以使用机器学习对商品进行分类,以此建立模型对其他新品进行预测。

猜你喜欢

转载自blog.csdn.net/zongzi009/article/details/82355760