數(shù)據(jù)分析的流程:
1、明確分析目的和思路/提出假設(shè)
2、數(shù)據(jù)收集
3、數(shù)據(jù)處理/整理
4、數(shù)據(jù)分析/驗(yàn)證假設(shè)
5、數(shù)據(jù)展現(xiàn)/可視化圖表
6、報(bào)告撰寫(xiě)
1.分析背景
2019年,平臺(tái)經(jīng)過(guò)一年的發(fā)展,銷(xiāo)售體量、客戶(hù)群體、平臺(tái)規(guī)模達(dá)到新的高度。
現(xiàn)對(duì)平臺(tái)2019年銷(xiāo)售數(shù)據(jù)進(jìn)行分析。
分析數(shù)據(jù):(10萬(wàn)+)
2019-01-01-00:00:00 --- 2019-12-31-23:59:59
2.分析思路
2.1.整體運(yùn)營(yíng)
2.2.用戶(hù)行為
2.3.銷(xiāo)售
2.4.渠道流量
3.分析過(guò)程
3.1.整體運(yùn)營(yíng):
--->GMV,成交總額,凈成交總額
--->成交總額占GMV
--->凈成交總額占GMV
--->退貨率(退單數(shù)/總單)
3.2.銷(xiāo)售:
--->每個(gè)月的銷(xiāo)售趨勢(shì)折線(xiàn)圖【GMV,銷(xiāo)售額,不含退單】
【關(guān)注最高點(diǎn),最低點(diǎn),上升點(diǎn)】
--->銷(xiāo)售復(fù)購(gòu)率
3.3.流量分析:
--->渠道來(lái)源用戶(hù)對(duì)比
3.4.用戶(hù)分析:
--->每周訂單量【用來(lái)調(diào)整平臺(tái)人員的作息時(shí)間】
--->一天當(dāng)中活躍時(shí)間段
--->RFM模型【針對(duì)不同層次的客戶(hù)制定相應(yīng)的策略】
4.結(jié)論建議
4.1.整體運(yùn)營(yíng):
提高GMV,成交額,凈成交額
4.2.銷(xiāo)售:
5月、11月運(yùn)營(yíng)促銷(xiāo)策略推廣;復(fù)購(gòu)率低,平臺(tái)數(shù)據(jù)加強(qiáng)用戶(hù)銷(xiāo)售數(shù)據(jù)埋點(diǎn)
4.3.流量:
提高渠道-0896,渠道-9527,渠道-0530流量投入更改或暫停渠道-330,渠道-0318,渠道-0191流量
一.加載數(shù)據(jù)
#1.加載處理數(shù)據(jù)所需要的庫(kù)
import pandas as pd
#2.讀取數(shù)據(jù)文件
#添加索引,不然默認(rèn)的要加一列且從0開(kāi)始
df = pd.read_excel('order2019.xlsx',index_col='id')
df.head()#104557

二.提取數(shù)據(jù)
2.1根據(jù)業(yè)務(wù)需要提取數(shù)據(jù),提取2019年數(shù)據(jù)
#1.引入時(shí)間模塊, 確定周期時(shí)間
import datetime
#2.確定開(kāi)始時(shí)間節(jié)點(diǎn)與結(jié)束時(shí)間節(jié)點(diǎn)
# 2019,1,1,0,0,0
startTime = datetime.datetime(2019, 1, 1)
endTime = datetime.datetime(2019, 12, 31, 23, 59, 59)
#3.將數(shù)據(jù)源中的時(shí)間數(shù)據(jù)轉(zhuǎn)換成datetime形式 (以防是字符串)
# print(type(df['orderTime']))
df.orderTime = pd.to_datetime(df.orderTime)
#4.將2019年1月1日前數(shù)據(jù)刪除
df[df.orderTime < startTime] # True False
#刪除數(shù)據(jù) drop(index="索引", inplace=True,False)
df.drop(index=df[df.orderTime < startTime].index, inplace=True)#在df上直接修改
df
#5.將2019年12月31日后數(shù)據(jù)刪除
df[df.orderTime > endTime]
df.drop(index=df[df.orderTime > endTime].index, inplace=True)
df #104296

2.2提取數(shù)據(jù)時(shí),處理與業(yè)務(wù)流程不符合數(shù)據(jù),支付時(shí)間間隔過(guò)長(zhǎng)
#1.下單時(shí)間與支付時(shí)間間隔 (創(chuàng)建一個(gè)新字段)
df['payinterval'] = (df.payTime-df.orderTime).dt.total_seconds()#間隔都轉(zhuǎn)化成秒
df
#2.支付時(shí)間間隔大于30分鐘與支付時(shí)間早于下單時(shí)間
df[df.payinterval>1800]
df.drop(index=df[df.payinterval>1800].index, inplace=True)
df.drop(index=df[df.payinterval<0].index, inplace=True)
df #103354

2.3提取數(shù)據(jù)時(shí),處理與業(yè)務(wù)流程不符合數(shù)據(jù),訂單金額與支付金額為負(fù)
# 1.訂單金額為負(fù)
df[df.orderAmount < 0]
# # # 2.付款金額為負(fù)
df[df.payment < 0]#(優(yōu)惠券的面額大于商品價(jià)格)
# # # 3.刪除相應(yīng)訂單
df.drop(index=df[df.payment < 0].index, inplace=True)
df.head() #103348

三.清洗數(shù)據(jù)
3.1 查看數(shù)據(jù)
#1.查看非空信息
df.info()
#2. 查看整體描述
# df.describe()#對(duì)數(shù)值型的數(shù)據(jù)作基本描述

3.2 清洗orderID
#1.訂單orderID不重復(fù)的個(gè)數(shù)
df.orderID.unique().size #103321
# df.orderID.size #103348
# 2.刪除重復(fù)數(shù)據(jù)
df.drop(index=df[df.orderID.duplicated()].index, inplace=True)
df.info() #103321

3.3 清洗userID
#用戶(hù)個(gè)數(shù)
df.userID.unique().size #78634
df.userID.size #103321
#復(fù)購(gòu)用戶(hù),正常的
3.4 清洗goodsID
#PR000000
#商品下架 這個(gè)得結(jié)合業(yè)務(wù)知識(shí),哪種代號(hào)表示下架商品
df.goodsID[df.goodsID == 'PR000000'].size #175
df.drop(index=df[df.goodsID == 'PR000000'].index, inplace=True)
df.info() #103146
3.5 清洗chanelID
#1.查看chanelID空值的信息
df[df.chanelID.isnull()]#是空為T(mén)rue
# #2.對(duì)空值進(jìn)行修補(bǔ)
# value= inplace
df['chanelID'].fillna(value=df.chanelID.mode()[0], inplace=True)
df.info()
3.6 清洗platformtype
#由于空格的存在導(dǎo)致了成為了不同
df.platformType.unique().size #不重復(fù)的有幾個(gè)
df.platformType.unique()#不重復(fù)的是哪幾個(gè)
# " "字符串,存在空格 "" 空字符串
df['platformType']=df['platformType'].str.replace(" ","")
df.platformType.unique()

3.7 清洗payment
#【支付金額大于訂單金額】,則計(jì)算平均折扣,用訂單金額*平均折扣
#1.創(chuàng)建折扣字段
df['discount'] = (df.payment/df.orderAmount)
df.describe()
# 200, 200 190
#2.平均折扣(已經(jīng)排查了異常數(shù)據(jù))
meanDiscount = df[df['discount']<=1].discount.sum() / df[df['discount']<=1].discount.size
meanDiscount
#3.找到折扣大于1的數(shù)據(jù)
df[df['discount']>1]
df['payment'] = df['payment'].mask(df['discount']>1,None)
#mask,一一對(duì)應(yīng)的,就是discount>1,就設(shè)置為None,類(lèi)似于map函數(shù)
#4.對(duì)折扣大于1的數(shù)據(jù)進(jìn)行填補(bǔ)
df['payment'].fillna(value=df.orderAmount*meanDiscount , inplace=True)
df.info()
# #5.處理折扣
df['discount'] = round((df.payment/df.orderAmount),2)
df
3.8清洗結(jié)束 查看數(shù)據(jù)
df.describe()
四.分析數(shù)據(jù)
4.1.分析數(shù)據(jù),整體銷(xiāo)售情況
#總體概覽
# 1.銷(xiāo)售GMV
df.orderAmount.sum()/10000 #10835
# # 2.成交總和
df.payment.sum()/10000 #10246
# # # 3.實(shí)際成交額
df[df.chargeback=="否"].payment.sum()/10000 # 8879
# # # 4.訂單數(shù)量
df.orderID.unique().size #103146
# # # 5.退貨訂單數(shù)
df[df.chargeback=="是"].orderID.size #13590
# # # 6.退貨率 (15%算低的了)
df[df.chargeback=="是"].orderID.size/df.orderID.unique().size
# # # 7.用戶(hù)數(shù)
df.userID.unique().size #78525
4.2銷(xiāo)售情況,各月份GMV\成交額趨勢(shì)
#翻轉(zhuǎn)維度,以月份為坐標(biāo)軸
#1.月份字段
df['month'] = df['orderTime'].dt.month
df
#2.繪制圖形
#2.1引入相應(yīng)的庫(kù)
import matplotlib.pyplot as plt
from matplotlib import font_manager #管理字體
#能夠讓圖在這里面立即展示
%matplotlib inline
#2.2設(shè)置字體(照寫(xiě))
#mac linux fc-list : lang= zh
my_font = font_manager.FontProperties(fname='C:\Windows\Fonts\msyh.ttc',size=12)
#2.3設(shè)置畫(huà)布大小
plt.figure(figsize=(10,6))
#2.4設(shè)置網(wǎng)格線(xiàn) 輔助線(xiàn)
plt.grid(alpha=0.4)
# #2.5橫縱坐標(biāo)值
# #所有橫坐標(biāo)都一致
x = df.groupby('month')['orderAmount'].sum().index
x
# #GMV
y1 = df.groupby('month')['orderAmount'].sum().values/10000
#銷(xiāo)售實(shí)際付款
y2 = df.groupby('month')['payment'].sum().values/10000
#不含退單銷(xiāo)售額
y3 = df[df.chargeback=="否"].groupby('month')['payment'].sum().values/10000
#2.6 X橫軸坐標(biāo)文字
x_ticks_label = ["{}月份".format(i) for i in x]
# x刻度,標(biāo)簽文字
plt.xticks(x,x_ticks_label,rotation = 45,fontproperties = my_font)
#2.7繪制三條折線(xiàn)走勢(shì)
#plot 折線(xiàn)圖
#color 單詞,#0022FF rgb(0,255)
plt.plot(x,y1,label='GMV',color="red",marker='o')
plt.plot(x,y2,label='銷(xiāo)售額',color="orange",marker='*')
plt.plot(x,y3,label='不含退單',color="blue",marker = '.')
#2.8標(biāo)記橫縱軸名字與標(biāo)題
plt.xlabel('月份',fontproperties=my_font)
plt.ylabel("銷(xiāo)售額萬(wàn)元",fontproperties=my_font)
plt.title('銷(xiāo)售額走勢(shì)',fontproperties=my_font,color='red',size=20)
#2.9添加折點(diǎn)坐標(biāo)
for a,b in zip(x,y1):
plt.annotate('(%.2f)'%(b),xy=(a,b),xytext=(-10,10),textcoords='offset points')
#2.10設(shè)置圖例
plt.legend(prop=my_font,loc='upper left')
#2.11顯示圖形
plt.show()

4.3 流量渠道來(lái)源分析
#1.按照渠道分組聚合,統(tǒng)計(jì)用戶(hù)數(shù)
custom = df.groupby('chanelID')['userID'].count()
custom
#2.設(shè)置字體
plt.rcParams['font.sans-serif']=['SimHei']
#3.使用pandas中方法直接畫(huà)圖
#pandas % 1.1f% %
custom.plot.pie(figsize=(15,10),labels=custom.index,autopct="%1.1f%%")
#4.設(shè)置標(biāo)題
plt.title('各渠道來(lái)源用戶(hù)占比')
plt.savefig('t2.png')

4.4 用戶(hù)行為, 研究周一到周日哪天訂單量最高
#1.處理周幾字段
df['dayofweek'] = df['orderTime'].dt.dayofweek
df['dayofweek'].unique() #【1,2,3,4,5,6,0】
# #2.引入numpy
import numpy as np
#3.按周幾做聚合
week = df.groupby('dayofweek')['orderID'].count()
week
# #4.設(shè)置橫縱坐標(biāo)
weekX = ['周一','周二','周三','周四','周五','周六','周日']
weekY = week.values
# weekX
#5.設(shè)置X軸
#刻度,值,字體
plt.xticks(range(len(weekX)),weekX,fontproperties=my_font)
# # #6.設(shè)置條形圖
rects = plt.bar(range(len(weekX)),weekY,width=0.3,color=['r','g','b'])
# #7.設(shè)置每個(gè)數(shù)據(jù)條的位置
for rect in rects:
height = rect.get_height()#拿到每個(gè)條的高度
plt.text(rect.get_x() + rect.get_width() / 2, height+0.5, str(height),ha="center")
#第一個(gè)參數(shù):使得數(shù)據(jù)在柱子的正中間,
# #8.顯示
plt.show()

4.5 用戶(hù)行為, 哪個(gè)時(shí)間段下單量最高
#1.備份整個(gè)數(shù)據(jù)
df1 = df.copy()
df1
# df1 = df 這是錯(cuò)誤的,他們是對(duì)象類(lèi)型,不能直接引用
# #2.設(shè)置時(shí)間周期30min
s = df1['orderTime'].dt.floor('30T') #直接在ordertime上面改
s #顯示每條記錄的時(shí)間段(30分鐘為一段,年月日時(shí)分秒)
# #3.將下單時(shí)間轉(zhuǎn)換成時(shí)間段
df1['orderTime'] = s.dt.strftime('%H:%M') + '-' + (s + pd.Timedelta(30 * 60, unit='s')).dt.strftime('%H:%M')
df1#時(shí)間段,00:00-00:30 ~ 23:30-00:00
# # #4.根據(jù)時(shí)間段分組聚合
tiemdf = df1.groupby('orderTime')['orderID'].count()
tiemdf
tiemdfX = tiemdf.index #各個(gè)時(shí)間段
tiemdfY = tiemdf.values#每個(gè)時(shí)間段里的訂單量
tiemdfY
# #5.設(shè)置畫(huà)布大小
plt.figure(figsize=(20,8),dpi=80 ) #分辨率
#6.設(shè)置樣式風(fēng)格
plt.style.use('ggplot')
#7.X軸形式
plt.xticks(range(len(tiemdfX)),tiemdfX,rotation=90)
#8.繪制數(shù)據(jù)條形圖
rect = plt.bar(tiemdfX,tiemdfY,width=0.3,color=['orange'])
plt.title('用戶(hù)下單時(shí)間段研究')
plt.savefig('t3.png')
#波峰的時(shí)候:搶購(gòu)活動(dòng)(中午休息的時(shí)間)
#波谷的時(shí)候:更新什么

4.6用戶(hù)行為,客戶(hù)情況
#1.客單價(jià) 訂單總金額/去重的用戶(hù)總數(shù)【每個(gè)用戶(hù)貢獻(xiàn)的金額】
df.orderAmount.sum()/df.userID.unique().size #1379.8
需要將userID作為一個(gè)純粹的索引
#需要將userID作為一個(gè)純粹的索引
#因?yàn)檫@里全為user-的形式
#如果數(shù)字前面有 user-,哈哈-,呵呵- 等,那么就轉(zhuǎn)化成11,22,33等數(shù)字形式
#1.檢查數(shù)據(jù)字段
df['userid'] = df["userID"].str[0:4]
df['userid'].unique() #user
df['userid'].unique().size #1,說(shuō)明都是user
#2.userID只保留數(shù)字
df['userID'] = df["userID"].str[5:]
df
4.7用戶(hù)行為,客戶(hù)復(fù)購(gòu)率
# 分析復(fù)購(gòu)率
# 將用戶(hù)消費(fèi)數(shù)據(jù)進(jìn)行數(shù)據(jù)透視。
# 統(tǒng)計(jì)每個(gè)用戶(hù)在每月的訂單量,所以u(píng)serID是index,month是column。
pivoted_counts=df.pivot_table(index='userID',columns='month',
values='orderTime',aggfunc='count').fillna(0)
pivoted_counts.head()
# pivoted_counts=df.pivot_table(index='userID',
# values='orderTime',aggfunc='count').fillna(0)
#每個(gè)用戶(hù)一整年的復(fù)購(gòu)情況
pivoted_counts.sum() #按照每個(gè)月
# pivoted_counts.count() #按照每個(gè)月,只不過(guò)每個(gè)月都一樣 78525


#復(fù)購(gòu)率
#區(qū)分出沒(méi)有購(gòu)買(mǎi)的,購(gòu)買(mǎi)1次的,1次以上的
# 復(fù)購(gòu)率的定義是在某時(shí)間窗口內(nèi)消費(fèi)兩次及以上的用戶(hù)在總消費(fèi)用戶(hù)中占比。這里的時(shí)間窗口是月。
# if x>1 :
# x = 1
# else :
# if x==0:
# np.NaN
# else :
# 0
#1.引入numpy
import numpy as np
#2. 將數(shù)據(jù)轉(zhuǎn)換一下,消費(fèi)兩次及以上記為1,消費(fèi)一次記為0,沒(méi)有消費(fèi)記為NaN。
pcRepeatBuy =pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
pcRepeatBuy.head()
#3.繪圖
#用sum和count相除即可計(jì)算出復(fù)購(gòu)率。
(pcRepeatBuy.sum()/pcRepeatBuy.count()).plot(figsize=(15,6))
pcRepeatBuy.sum() #兩次以上的消費(fèi)用戶(hù)數(shù)
pcRepeatBuy.count() #總的消費(fèi)用戶(hù)數(shù)(NaN值不計(jì)數(shù))
plt.savefig('t4.png')

4.8用戶(hù)行為,客戶(hù)RFM模型
#RFM根據(jù)用戶(hù)的活躍程度,頻率,貢獻(xiàn)程度 分類(lèi)
# Recency 最后一次消費(fèi)距離現(xiàn)在時(shí)間距離 R越小越好,
# Frequency 消費(fèi)頻率 F越大越好
# Monetary 消費(fèi)金額 M越大越好
# 8類(lèi)用戶(hù), 打標(biāo)簽
#1.備份整個(gè)數(shù)據(jù)
customdf = df.copy()
# 問(wèn)題:什么時(shí)候需要復(fù)制數(shù)據(jù),什么時(shí)候直接修改
#2.刪除退單
customdf.drop(index=df[df.chargeback == '是'].index, inplace=True)
customdf
#3.轉(zhuǎn)換日期格式
customdf['orderTime'] = customdf['orderTime'].dt.date #只顯示年月日
# customdf['orderTime'] = pd.to_datetime(customdf['orderTime'], format='%Y-%m-%d')
customdf
# #4.將userID設(shè)置為索引,即去除了原有的ID號(hào)
customdf.set_index('userID',drop=True,inplace=True)
# #5.將原始訂單中訂單量全部置為1
customdf['orders'] = 1
customdf
# #6.數(shù)據(jù)透視
rfmdf = customdf.pivot_table(index=['userID'],
values=['orderAmount','orderTime','orders'],
aggfunc={'orderTime':'max',
'orderAmount':'sum',
'orders':'sum'})
rfmdf
#7.處理RFM模型中的R
#最后一個(gè)單子的時(shí)間和每一個(gè)用戶(hù)的單子時(shí)間相減,轉(zhuǎn)化為天數(shù)
rfmdf['R'] = (rfmdf.orderTime.max()-rfmdf.orderTime).dt.days
#8.處理RFM模型中的F與M
rfmdf.rename(columns={'orderAmount':'M','orders':'F'},inplace=True)
rfmdf.head()

#1. 對(duì)用戶(hù)分類(lèi),設(shè)置標(biāo)簽
def rfm_func(x):
level = x.apply(lambda x: "1" if x >= 1 else '0')
label = level.R + level.F + level.M
d = {
'011':'重要價(jià)值客戶(hù)',
'111':'重要喚回客戶(hù)',
'001':'重要深耕客戶(hù)',
'101':'重要挽留客戶(hù)',
'010':'潛力客戶(hù)',
'110':'一般維持客戶(hù)',
'000':'新客戶(hù)',
'100':'流失客戶(hù)'
}
result = d[label]
return result
#2.根據(jù)模型打標(biāo)簽
rfmdf['label'] = rfmdf[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
#3.分組聚合
rfmdf_res = rfmdf.groupby('label').count()
rfmdf_res

#1.繪制圖形
rfmdf.label.value_counts().plot.bar(figsize=(20,9))
#2.設(shè)置X軸
plt.xticks(rotation=0,fontproperties=my_font)
