欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于bokeh的数据分析——电商套路解析

程序员文章站 2022-04-14 22:52:03
...

项目目标
一: 从现有数据中,分析出“各个品牌都有多少商品参加了双十一活动
导入模块

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

import warnings
warnings.filterwarnings('ignore')

from bokeh.plotting import figure,show,output_file
from bokeh.models import ColumnDataSource

导入双十一电商打折套路解析数据集,并进行基本的数据处理

import os
os.chdir('E:/Python数据分析电商打折套路解析')
df=pd.read_excel('双十一淘宝美妆数据.xlsx',sheet_name=0)
df.fillna(0,inplace=True)
df.index=df['update_time']
df['date']=df.index.day

对数据进行筛选,统计不同商品的销售开始,结束日期

data1=df[['id','title','店名','date']]#筛选数据
d1=data1[['id','date']].groupby(by='id').agg(['min','max'])['date']#统计不同商品的的销售开始,结束日期

id_11=data1[data1['date']==11]['id']#筛选双十当天买的商品id
id_11=data1[data1['date']==11]['id']
d2=pd.DataFrame({'id':id_11,'双十一当天是否售卖':True})
id_data=pd.merge(d1,d2,left_index=True,right_on='id',how='left')
id_data.fillna(False,inplace=True)
m=len(d1)
m_11=len(id_11)
m_pre=m_11/m
d2=pd.DataFrame({'id':id_11,'双十一当天是否售卖':True})

按照商品销售节奏分类,我们可以将商品分为7类
A. 11.11前后及当天都在售 → 一直在售
B. 11.11之后停止销售 → 双十一后停止销售
C. 11.11开始销售并当天不停止 → 双十一当天上架并持续在售
D. 11.11开始销售且当天停止 → 仅双十一当天有售
E. 11.5 - 11.10 → 双十一前停止销售
F. 仅11.11当天停止销售 → 仅双十一当天停止销售
G. 11.12开始销售 → 双十一后上架

d2=pd.DataFrame({'id':id_11,'双十一当天是否售卖':True})
id_data['type']='待分类'
id_data['type'][(id_data['min']<11)&(id_data['max']>11)]='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['双十一当天是否售卖']==False]='F'
id_data['type'][id_data['min']>11]='G'

销售数据分类

result1=id_data['type'].value_counts()
print(result1)
result1=result1.loc[['A','B','C','D','E','F','G']]

未参与双十一当天活动的商品,可能有四种情况:
con1 → 暂时下架(F)
con2 → 重新上架(E中部分数据,数据中同一个id可能有不同title,“换个马甲重新上架”),字符串查找特定字符 dataframe.str.contains(‘预售’)
con3 → 预售(E中部分数据,预售商品的title中包含“预售”二字)

from bokeh.palettes import brewer
colori=brewer['YLGn'][7]
plt.axis('equal1')
plt.pie(result1,labels=result1.index,autopct='%.2f%%',colors=colori,startangle=90,radius=1.5,counterclock=False)
#未参与双十一当天活动的商品,去向如何
id_not11=id_data[id_data['双十一当天是否售卖']==False]
data_not11=id_not11[['id','type']]
df_not11=id_not11[['id','type']]
data_not11=pd.merge(df_not11,df,on='id',how='left')
#找到双十一当天未参加活动商品对于的原始数据
id_con1=id_data['id'][id_data['type']=='F'].values
#筛选出con1
data_con2=data_not11[['id','title','date']].groupby(by=['id','title']).count()
title_count=data_con2.reset_index()['id'].value_counts()
data_not11[data_not11['id']=='A536510937963']
id_con2=title_count[title_count>1].index
#筛选出con2
data_con3=data_not11[data_not11['title'].str.contains('预售')]
id_con3=data_con3['id'].value_counts().index
#print('未参与双十一当天活动的商品中:%i个为暂时下架商品。%i为重新上架商品,%i个为预售商品' %(len(id_con1),len(id_con2),len(id_con3)))
#真正参与双十一活动的商品及品牌情况
#真正参加活动的商品 = 双十一当天在售的商品 + 预售商品 (可以尝试结果去重)
data_11sale=id_11

id_11sale_final=np.hstack((data_11sale,id_con3))

result2_i=pd.DataFrame({'id':id_11sale_final})

堆叠图的制作,直观看出商品的预售和实际售出

x1=pd.DataFrame({'id':id_11})

x1_df=pd.merge(x1,df,on='id',how='left')

brand_11sale=x1_df.groupby('店名')['id'].count()
#不同品牌当天参与双十一的商品数量

x2=pd.DataFrame({'id':id_con3})

x2_df=pd.merge(x2,df,on='id',how='left')

brand_ys=x2_df.groupby('店名')['id'].count()
#不同品牌预售的商品数量
result2_data=pd.DataFrame({'当天参与活动商品数量':brand_11sale,'预售商品数量':brand_ys})
result2_data['总量']=result2_data['当天参与活动商品数量']+result2_data['预售商品数量']
result2_data.sort_values(by='总量',inplace=True,ascending=False)
#计算结果
#堆叠图制作
from bokeh.models import HoverTool
from bokeh.core.properties import value
lst_brand=result2_data.index.tolist()
lst_type=result2_data.columns.tolist()[:2]
colors=['red','green']
#基本参数
result2_data.index.name='brand'
result2_data.columns=['sale_on_11','prese11','sum']
source=ColumnDataSource(result2_data)
hover=HoverTool(tooltips=[('品牌','@brand'),
                          ('双十一当天参与活动的商品数量','@sale_on_11'),
                          ('预售商品数量','@prese11'),
                          ('真正参与双十一活动的商品总数','@sum')])
output_file('project08_pic1.htm1')
p=figure(x_range=lst_brand,plot_width=900,plot_height=350,
         title='各个品牌参与双十一活动的情况',
         tools=[hover,'reset,xwheel_zoom,pan,crosshair'])
p.vbar_stack(lst_type,x='brand',
             source=source,width=0.9,
             color=colors,alpha=0.7,
             legend=[value(x)for x in lst_type],
             muted_color='black',
             muted_alpha=0.2)
show(p)

基于bokeh的数据分析——电商套路解析
二,打折情况的判断
① 打折情况评估方法:
真打折:商品的价格在10天内有波动、双11价格为10天内最低价、不存在涨价现象
不打折:商品价格无变化
② 针对每个商品做price字段的value值统计,查看价格是否有波动,可以先用pd.cut将date分为不同周期:‘双十一前’,‘双十一当天’,‘双十一后’,得到period字段
data[[‘id’,‘price’,‘date’]].groupby([‘id’,‘price’]).min()
针对统计出来的结果,如果按照id和price分组仍只有一个唯一值,则说明价格未变,没打折;否则为打折

data2=df[['id','title','店名','date','price']]
data2['period']=pd.cut(data2['date'],[4,10,11,14],labels=['双十一前','双十一当天','双十一后'])
#筛选数据
price=data2[['id','price','period']].groupby(['id','price']).min()
#查看数据是否有波动
price.reset_index(inplace=True)
id_count=price['id'].value_counts()
id_type1=id_count[id_count==1].index
id_type2=id_count[id_count!=1].index
#筛选出不打折与打折


#针对在打折的商品,其折扣率是多少
result3_data1=data2[['id','price','period','店名']].groupby(['id','price']).min()
result3_data1.reset_index(inplace=True)
#筛选数据
result3_data1.reset_index(inplace=True)

result3_before11=result3_data1[result3_data1['period']=='双十一前']

result3_at11=result3_data1[result3_data1['period']=='双十一当天']

result3_data2=pd.merge(result3_before11,result3_at11,on='id')
#合并数据
result3_data2['zkl']=result3_data2['price_y']/result3_data2['price_x']
#计算折扣率
bokeh_data=result3_data2[['id','zkl']].dropna()
bokeh_data['zkl_range']=pd.cut(bokeh_data['zkl'],bins=np.linspace(0,1,21))

bokeh_data2=bokeh_data.groupby('zkl_range').count().iloc[:-1]

bokeh_data2['zkl_pre']=bokeh_data2['zkl']/bokeh_data2['zkl'].sum()
#折扣区间的占比
output_file('project8_price2.html')
source1=ColumnDataSource(bokeh_data2)
lst_zkl=bokeh_data2.index.tolist()
hover=HoverTool(tooltips=[('折扣率','@zkl')])

p=figure(x_range = lst_zkl,plot_width=900,plot_height=350,title='商品折扣率统计',
         tools=[hover,'reset,xwheel_zoom,pan,crosshair'])
p.line(x='zkl_range',y='zkl_pre',source=source1,line_color='black',line_dash=[10,4])
p.cricle(x='zkl_range',y='zkl_pre',source=source1,size=8,color='red',alpha=0.8)

show(p)

折扣率 = 双十一当天价格 / 双十一之前价格
作图过程中,清除掉折扣率大于95%的数据
基于bokeh的数据分析——电商套路解析

# 解析出不同品牌的参与打折商品比例及折扣力度,并做散点图,总结打折套路

data_zk = result3_data2[result3_data2['zkl']<0.95]  # 删除未打折数据
result4_zkld = data_zk.groupby('店名_y')['zkl'].mean()
# 筛选出不同品牌的折扣率

n_dz = data_zk['店名_y'].value_counts()
n_zs = result3_data2['店名_y'].value_counts()
result4_dzspbl = pd.DataFrame({'打折商品数':n_dz,'商品总数':n_zs})
result4_dzspbl['参与打折商品比例'] = result4_dzspbl['打折商品数'] / result4_dzspbl['商品总数']
result4_dzspbl.dropna(inplace = True)
#print(result4_dzspbl.head())
# 计算出不同品牌参与打折商品比例

result4_sum = result2_data.copy()
# 筛选出品牌参加双11活动的商品总数

result4_data = pd.merge(pd.DataFrame(result4_zkld),result4_dzspbl,left_index = True, right_index = True, how = 'inner')
result4_data = pd.merge(result4_data,result4_sum,left_index = True, right_index = True, how = 'inner')
# 合并数据

散点图的绘制, 用bokeh绘制浮动散点图,y坐标为品牌类型,x坐标为折扣力度

from bokeh.models.annotations import Span            # 导入Span模块
from bokeh.models.annotations import Label           # 导入Label模块
from bokeh.models.annotations import BoxAnnotation   # 导入BoxAnnotation模块


bokeh_data = result4_data[['zkl','sum','参与打折商品比例']]
bokeh_data.columns = ['zkl','amount','pre']
bokeh_data['size'] = bokeh_data['amount'] * 0.03
source = ColumnDataSource(bokeh_data)
# 创建ColumnDataSource数据

x_mean = bokeh_data['pre'].mean()
y_mean = bokeh_data['zkl'].mean()

hover = HoverTool(tooltips=[("品牌", "@index"),
                            ("折扣率", "@zkl"),
                            ("商品总数", "@amount"),
                            ("参与打折商品比例", "@pre"),
                           ])  # 设置标签显示内容
p = figure(plot_width=600, plot_height=600,
                title="各个品牌打折套路解析" , 
                tools=[hover,'box_select,reset,wheel_zoom,pan,crosshair']) 
# 构建绘图空间

p.circle_x(x = 'pre',y = 'zkl',source = source,size = 'size',
           fill_color = 'red',line_color = 'black',fill_alpha = 0.6,line_dash = [8,3])
p.ygrid.grid_line_dash = [6, 4]
p.xgrid.grid_line_dash = [6, 4]
# 散点图

x = Span(location=x_mean, dimension='height', line_color='green',line_alpha = 0.7, line_width=1.5, line_dash = [6,4])
y = Span(location=y_mean, dimension='width', line_color='green',line_alpha = 0.7, line_width=1.5, line_dash = [6,4])
p.add_layout(x)
p.add_layout(y)
# 绘制辅助线

bg1 = BoxAnnotation(bottom=y_mean, right=x_mean,fill_alpha=0.1, fill_color='olive')
label1 = Label(x=0.1, y=0.55,text="少量大打折",text_font_size="10pt" )
p.add_layout(bg1)
p.add_layout(label1)
# 绘制第一象限

bg2 = BoxAnnotation(bottom=y_mean, left=x_mean,fill_alpha=0.1, fill_color='firebrick')
label2 = Label(x=0.7, y=0.55,text="大量大打折",text_font_size="10pt" )
p.add_layout(bg2)
p.add_layout(label2)
# 绘制第二象限

bg3 = BoxAnnotation(top=y_mean, right=x_mean,fill_alpha=0.1, fill_color='firebrick')
label3 = Label(x=0.1, y=0.80,text="少量少打折",text_font_size="10pt" )
p.add_layout(bg3)
p.add_layout(label3)
# 绘制第三象限

bg4 = BoxAnnotation(top=y_mean, left=x_mean,fill_alpha=0.1, fill_color='olive')
label4 = Label(x=0.7, y=0.80,text="少量大打折",text_font_size="10pt" )
p.add_layout(bg4)
p.add_layout(label4)
# 绘制第四象限

show(p)

基于bokeh的数据分析——电商套路解析
结论:
少量少打折:包括雅诗兰黛、娇兰、兰蔻、薇姿、玉兰油等共5个品牌。
少量大打折:包括悦诗风吟、兰芝、欧珀莱等3个品牌。该类品牌的打折商品较少,但折扣力度较大。
大量小打折:包括妮维雅、美宝莲、蜜丝佛陀等3个品牌。该类型有半数以上的商品都参与了打折活动,但折扣力度并不大。
大量大打折:包括相宜本草、佰草集、自然堂等三大国产品牌。这些品牌不仅有90%以上的商品参与了折扣活动,而且折扣力度很大。