1682億,“淘寶+天貓”2017年雙十一交易總額。看到這數字,驚訝的同時,是否想到自己作為狂歡者的一份子,貢獻了多少數據。這全民狂歡的背后,蘊含多少商家的套路,你又是否知道呢?!
PS :
- 本文所用數據為2016年淘寶雙十一美妝商品數據
- 使用jupyter notebook ,python進行數據分析
- bokeh 為可視化圖表模塊
事不宜遲,馬上進入我們的分析環節
問題1:有多少美妝商品品牌參加了雙十一活動?
1.1 導入函數庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
% matplotlib inline
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模塊
1.2 導入數據文件
import os
os.chdir('E:\\數據分析\\項目08電商打折套路解析')
# 創建工作路徑
df = pd.read_excel('雙十一淘寶美妝數據.xlsx',sheetname=0,header=0,index_col=0)
df_length = len(df)
df_columns = df.columns.tolist()
df.fillna(0,inplace = True) # 填充缺失值
df['date'] = df.index.day # 提取銷售日期
1.3 對商品進行分類
根據商品雙十一前后銷售情況,大致可以把商品分為7種
A. 11.11前后及當天都在售 → 一直在售
B. 11.11之后停止銷售 → 雙十一后停止銷售
C. 11.11開始銷售并當天不停止 → 雙十一當天上架并持續在售
D. 11.11開始銷售且當天停止 → 僅雙十一當天有售
E. 11.5 - 11.10 → 雙十一前停止銷售
F. 僅11.11當天停止銷售 → 僅雙十一當天停止銷售
G. 11.12開始銷售 → 雙十一后上架
data1 = df[['id','title','店名','date']]
#print(data1.head())
# 篩選數據
d1 = data1[['id','date']].groupby(by = 'id').agg(['min','max'])['date']
# 統計不同商品的銷售開始日期、截止日期
id_11 = data1[data1['date']==11]['id'].unique()
d2 = pd.DataFrame({'id':id_11,'雙十一當天是否售賣':True})
# 篩選雙十一當天售賣的商品id
id_date = pd.merge(d1,d2,left_index=True,right_on='id',how = 'left')
id_date['雙十一當天是否售賣'][id_date['雙十一當天是否售賣']!=True] = False
#print(id_date.head())
# 合并數據
m = len(data1['id'].unique())
m_11 = len(id_11)
m_11_pre = m_11/m
print('商品總數為%i個\n-------' % m)
print('雙十一當天參與活動的商品總數為%i個,占比為%.2f%%\n-------' % (m_11,m_11_pre*100))
print('品牌總數為%i個\n' % len(data1['店名'].unique()),data1['店名'].unique())
# 統計
id_date['type'] = '待分類'
id_date['type'][(id_date['min'] <11)&(id_date['max']>11)] = 'A' # A類:11.11前后及當天都在售 → 一直在售
id_date['type'][(id_date['min'] <11)&(id_date['max']==11)] = 'B' # B類:11.11之后停止銷售 → 雙十一后停止銷售
id_date['type'][(id_date['min'] ==11)&(id_date['max']>11)] = 'C' # C類:11.11開始銷售并當天不停止 → 雙十一當天上架并持續在售
id_date['type'][(id_date['min'] ==11)&(id_date['max']==11)] = 'D' # D類:11.11開始銷售且當天停止 → 僅雙十一當天有售
id_date['type'][id_date['雙十一當天是否售賣']== False] = 'F' # F類:僅11.11當天停止銷售 → 僅雙十一當天停止銷售
id_date['type'][id_date['max']<11] = 'E' # E類:11.5 - 11.10 → 雙十一前停止銷售
id_date['type'][id_date['min'] >11] = 'G' # G類:11.11之后開始銷售 → 雙十一后上架
# 商品銷售節奏分類
result1 = id_date['type'].value_counts()
result1 = result1.loc[['A','C','B','D','E','F','G']] # 調整順序
# 計算不同類別的商品數量
from bokeh.palettes import brewer
colori = brewer['YlGn'][7]
plt.axis('equal')
plt.pie(result1,labels = result1.index, autopct='%.2f%%',pctdistance=0.8,labeldistance =1.1,
startangle=90, radius=1.5,counterclock=False, colors = colori)
# 繪制餅圖
result1
我們可以得知商品數量信息
觀察發現,雙十一前后持續銷售的商品只有51.97%,僅為一半。其次,雙十一節日前停止銷售的數量最多,為24.01%。雙十一結束后停止銷售數量同樣占比很大,為13.08%,合計37.09%。
可以猜測,商家為了迎合狂歡節日,在商品的選擇和折扣上有很大的波動計劃。對數據只在乎“折扣值”大小的用戶,很容易就陷入商家的糖果炮彈中。
二、哪些商品真正在打折?
2.1 計算打折情況
把商品打折情況分為兩種,一是真打折,價格為10天波動里的最低值,否則為不打折。
data2 = df[['id','title','店名','date','price']]
data2['period'] = pd.cut(data2['date'],[4,10,11,14],labels = ['雙十一前','雙十一當天','雙十一后'])
#print(data2.head())
# 篩選數據
price = data2[['id','price','period']].groupby(['id','price']).min()
price.reset_index(inplace = True)
# 針對每個商品做price字段的value值統計,查看價格是否有波動
id_count = price['id'].value_counts()
id_type1 = id_count[id_count == 1].index
id_type2 = id_count[id_count != 1].index
# 篩選出“不打折”和“真打折”的商品id
n1 = len(id_type1)
n2 = len(id_type2)
print('真打折的商品數量約占比%.2f%%,不打折的商品數量約占比%.2f%%' % (n2/len(id_count)*100, n1/len(id_count)*100))
僅僅只有24.73%,雙十一到底是用戶的狂歡,還是商家的狂歡,或許你已經有些許答案。
2.2 計算折扣率
為了清晰地呈現各品牌雙十一打折情況,多角度分析,我們再來計算商品的折扣率,大致查看折扣的分布情況
result3_data1 = data2[['id','price','period','店名']].groupby(['id','period']).min()
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_at11,result3_before11,on = 'id')
# 篩選出商品雙十一當天及雙十一之前的價格
result3_data2['zkl'] = result3_data2['price_x'] / result3_data2['price_y']
# 計算折扣率
# 用bokeh繪制折線圖:x軸為折扣率,y軸為商品數量占比
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] # 這里去掉折扣率在0.95-1之間的數據,該區間內數據zkl大部分為1,不打折
bokeh_data2['zkl_pre'] = bokeh_data2['zkl']/bokeh_data2['zkl'].sum()
# 將數據按照折扣率拆分為不同區間,并統計不同1扣率的商品數量
source = ColumnDataSource(data=bokeh_data2)
# 創建數據
lst_brand = bokeh_data2.index.tolist()
hover = HoverTool(tooltips=[("折扣率", "@zkl")]) # 設置標簽顯示內容
p = figure(x_range=lst_brand, plot_width=900, plot_height=350, title="商品折扣率統計",
tools=[hover,'reset,xwheel_zoom,pan,crosshair'])
# 構建繪圖空間
p.line(x='zkl_range',y='zkl_pre',source = source, # 設置x,y值, source → 數據源
line_width=2, line_alpha = 0.8, line_color = 'black',line_dash = [10,4]) # 線型基本設置
# 繪制折線圖
p.circle(x='zkl_range',y='zkl_pre',source = source, size = 8,color = 'red',alpha = 0.8)
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
# 設置其他參數
show(p)
商品折扣出現兩個波峰,一個是8.5折到9折,此類折扣最為常見,既響應了狂歡節的打折信號,又不會把價格定得過低造成虧損,屬于人畜無害的一種手段,誠然也是最普遍的套路。
喜聞樂見的是,第二個波峰在4.5折到5折,這類商品的口號往往是限量半價發售,或是第二件半價,旨在快速積累店鋪人氣,清理庫存商品。對于普羅大眾而言,這類商品才稱得上真正的狂歡。
其次,折扣力度越大,商品量越少實屬常見。低價商品多以秒殺為主,數量及其有限。當然,搶到就是賺到。
2.3 哪個品牌稱得上“良心商家”
# 用bokeh繪制浮動散點圖,y坐標為品牌類型,x坐標為折扣力度
from bokeh.transform import jitter
brands = result3_data2['店名_y'].dropna().unique().tolist()
# 得到y坐標
bokeh_data = result3_data2[['id','zkl','店名_y']].dropna()
bokeh_data = bokeh_data[bokeh_data['zkl'] < 0.95]
source = ColumnDataSource(data = bokeh_data)
# 創建數據
hover = HoverTool(tooltips=[("折扣率", "@zkl")]) # 設置標簽顯示內容
p = figure(plot_width=800, plot_height=600,y_range=brands,title="不同品牌折扣率情況",
tools=[hover,'reset,ywheel_zoom,pan,crosshair'])
p.circle(x='zkl',
y=jitter('店名_y', width=0.6, range=p.y_range),
source=source, alpha=0.3)
# jitter參數 → 'day':第一參數,這里指y的值,width:間隔寬度比例,range:分類范圍對象,這里和y軸的分類一致
p.ygrid.grid_line_color = None
# 設置其他參數
show(p)
可以發現,大多品牌的折扣都有幾個數據密集點,集中在5折8.5折前后,這與前文相對應。
細心觀察,可以發現兩個有趣的品牌銷售手段。伍草集有四個數據密集點,分別在5-8折內,同時在各個折扣值上都有涉獵。大膽猜測,伍草集的銷售計劃旨在廣撒網,多個價格區間搶占用戶,滿足多個階級人群需要。
反觀歐萊雅,折扣數據分別在超高折扣和低折扣,缺乏中間數值。可猜測,歐萊雅的商品更受高薪人群青睞,需要超高折扣吸引中層消費者,同時低折扣滿足原客戶需求。
三、商家營銷套路挖掘
最后,我們來匯總觀察不痛品牌的參與打折商品數值,并做成氣泡圖
# 解析出不同品牌的參與打折商品比例及折扣力度,并做散點圖,總結打折套路
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繪制散點圖,x軸為參與打折商品比例,y軸為折扣力度,點的大小代表該品牌參加雙11活動的商品總數
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)
運行代碼可得下圖。其中,x軸為參與打折商品比例,y軸為折扣力度,點的大小代表該品牌參加雙11活動的商品總數
總結:
品牌大致可分四類
- 少量少打折:包括雅詩蘭黛、嬌蘭、蘭蔻、薇姿、玉蘭油等共5個品牌。
- 少量大打折:包括悅詩風吟、蘭芝、歐珀萊等3個品牌。該類品牌的打折商品較少,但折扣力度較大。
- 大量小打折:包括妮維雅、美寶蓮、蜜絲佛陀等3個品牌。該類型有半數以上的商品都參與了打折活動,但折扣力度并不大。
- 大量大打折:包括相宜本草、佰草集、自然堂等三大國產品牌。這些品牌不僅有90%以上的商品參與了折扣活動,而且折扣力度很大。
看到現在,18年的雙十一,你還敢輕易“剁手”嗎?(大量大打折的還是不錯的,小聲嗶嗶)