Python 数据分析微专业课程--项目07 电商打折套路解析1.项目说明2.项目具体要求3.实现思路:4.实现过程:5.总结

    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)
    #饼图绘制
[/code]

![这里写图片描述](https://img-
blog.csdn.net/20180909202905163?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pvbmd6aTAwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

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

![这里写图片描述](https://img-
blog.csdn.net/20180909202931752?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pvbmd6aTAwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

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

![这里写图片描述](https://img-
blog.csdn.net/20180909203028167?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pvbmd6aTAwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

```code
    #绘制品牌打折情况图表
    
    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)
[/code]

![这里写图片描述](https://img-
blog.csdn.net/20180909203046871?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pvbmd6aTAwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

> > 说明:  
>  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之间进行均匀分布。
```code
    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)
[/code]

![这里写图片描述](https://img-
blog.csdn.net/20180909203105191?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pvbmd6aTAwOQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

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

#  5.总结

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


![在这里插入图片描述](https://img-blog.csdnimg.cn/20210608151750993.gif)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值