數(shù)據(jù)分析---電商RFM模型

數(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
image.png

二.提取數(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 
image.png

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  
image.png

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 
image.png

三.清洗數(shù)據(jù)

3.1 查看數(shù)據(jù)

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

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
image.png

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()
image.png

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()
image.png

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')
image.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()
image.png

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í)候:更新什么
image.png

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
image.png

image.png
#復(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')
image.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()
image.png
#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
image.png
#1.繪制圖形
rfmdf.label.value_counts().plot.bar(figsize=(20,9))
#2.設(shè)置X軸
plt.xticks(rotation=0,fontproperties=my_font)
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容