基於RFM模型的客戶分析

客戶RFM模型分類

客戶類型 最近一次交易距離觀測窗口的天數(黏性) 累計交易頻次(忠誠度) 累計交易成交額(消費能力) 對應場景
重要價值客戶 + + + RFM都很大,優質客戶
重要召回客戶 - + + 成交量和成交額都很大,但是最近沒有交易,需要召回
重要發展客戶 + - + 成交額大,最近有交易,需要重點識別
重要挽留客戶 - - + 成交額大,潛在的價值客戶,需要挽留
潛力客戶 + + - 成交量大,且最近有交易,需要挖掘
新客戶 + - - 最近有交易,是新客戶,需要推廣
一般維持客戶 - + - 成交量大,但是貢獻不大,黏性也不高,一般維持
流失客戶 - - - 已經流失的客戶

客戶的價值分析:

(1)客戶羣1 —— FM很高,R較低,可以看做是重要召回客戶
(2)客戶羣2 —— RFM都偏低,屬於低價值客戶
(3)客戶羣3 —— R很高,但FM很低,屬於新客戶

客戶價值排名:

客戶羣1 ——1—— 重要召回
客戶羣2 ——2—— 流失客戶/低價值客戶
客戶羣3 ——3—— 新客戶

客戶特點:

(1)重要召回客戶:
成交量和成交額都很大,但是最近沒有交易,需要發掘其潛力方形
促使這類客戶在本公司消費和合作伙伴處消費。通過客戶價值提升,加強滿意度,促使成爲高價值客戶。

(2)流失客戶/低價值客戶:
客戶所乘坐航班乘坐次數F里程M低以及較長時間無乘坐。
他們可能是在公司打折促銷時纔會乘坐本公司航班。

(3)新客戶:
最近有交易,是新客戶,需要推廣。
增加與這類客戶的互動,瞭解情況,採取一定手段,讓客戶生命進一步成長。

實現步驟

  • 數據探索清洗
  • RFM屬性設計
  • 維度打分
  • 分值計算
  • 客戶分層
  • 描述統計並可視化
# 導包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib


plt.style.use('seaborn')
plt.rcParams["font.sans-serif"] = ["SimHei"] #顯示中文,解決圖中無法顯示中文的問題
plt.rcParams["axes.unicode_minus"] = False #設置顯示中文後,負號顯示受影響。解決座標軸上付好亂碼問題

數據探索和清洗

df  = pd.read_excel('PYTHON-RFM實戰數據.xlsx')
df.head()
品牌名稱 買家暱稱 付款日期 訂單狀態 實付金額 郵費 省份 城市 購買數量
0 wifi365 叫我李2 2019-01-01 00:17:59 交易成功 186 6 上海 上海市 1
1 wifi365 0cyb1992 2019-01-01 00:59:54 交易成功 145 0 廣東省 廣州市 1
2 wifi365 蘿污萌莉 2019-01-01 07:48:48 交易成功 194 8 山東省 東營市 1
3 wifi365 atblovemyy 2019-01-01 09:15:49 付款以後用戶退款成功,交易自動關閉 84 0 江蘇省 鎮江市 1
4 wifi365 小星期魚 2019-01-01 09:59:33 付款以後用戶退款成功,交易自動關閉 74 0 上海 上海市 1
# 刪除退款
df = df.loc[df['訂單狀態']=='交易成功',:]
df.shape
(27793, 9)
print ("列數     : " ,df.shape[0])
print ("行數  : " ,df.shape[1])
print ("\n特徵數量 : \n" ,df.columns.tolist())
print ("\n缺失值 :  ", df.isnull().sum().values.sum())
print ("\n唯一值 :  \n",df.nunique())
列數     :  27793
行數  :  9

特徵數量 : 
 ['品牌名稱', '買家暱稱', '付款日期', '訂單狀態', '實付金額', '郵費', '省份', '城市', '購買數量']

缺失值 :   1

唯一值 :  
 品牌名稱        1
買家暱稱    25420
付款日期    27283
訂單狀態        1
實付金額      280
郵費          6
省份         31
城市        345
購買數量       22
dtype: int64
# 刪除缺失值,重複值,把ID改爲字符類型
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True,inplace=True)
df.head(2)
品牌名稱 買家暱稱 付款日期 訂單狀態 實付金額 郵費 省份 城市 購買數量
0 wifi365 叫我李2 2019-01-01 00:17:59 交易成功 186 6 上海 上海市 1
1 wifi365 0cyb1992 2019-01-01 00:59:54 交易成功 145 0 廣東省 廣州市 1

RFM屬性設計

# 提取三個關鍵字段
df1 = df[['買家暱稱','付款日期','實付金額']]
df1['付款日期'] = pd.to_datetime(df1.付款日期)
C:\Users\Administrator\anaconda3\lib\site-packages\ipykernel_launcher.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  """Entry point for launching an IPython kernel.
df1.head()
買家暱稱 付款日期 實付金額
0 叫我李2 2019-01-01 00:17:59 186
1 0cyb1992 2019-01-01 00:59:54 145
2 蘿污萌莉 2019-01-01 07:48:48 194
3 重碎疊 2019-01-01 10:00:07 197
4 iho_jann 2019-01-01 10:00:08 168

R

# 由於同一個客戶對應不同的訂單,選取客戶付款日期的最大值
r = df1.groupby('買家暱稱')['付款日期'].max().reset_index()
r.head()
買家暱稱 付款日期
0 .blue_ram 2019-02-04 17:49:34.000
1 .christiny 2019-01-29 14:17:15.000
2 .willn1 2019-01-11 03:46:18.000
3 .託託m 2019-01-11 02:26:33.000
4 0000妮 2019-06-28 16:53:26.458
# 做時間差計算相隔的天數
r['R'] = (pd.to_datetime('2019-7-1')-r['付款日期']).dt.days
# 刪除無用特徵
r = r[['買家暱稱','R']]
r.head()
買家暱稱 R
0 .blue_ram 146
1 .christiny 152
2 .willn1 170
3 .託託m 170
4 0000妮 2

F

每個用戶累計的購買頻次:引入一個精確到天的日期標籤,依照買家和日期進行分組,將每個用戶一天內的多筆交易進行合併

# 引入日期標籤的輔助列
df['日期標籤'] = df['付款日期'].astype(str).str[:10]
df.head()
品牌名稱 買家暱稱 付款日期 訂單狀態 實付金額 郵費 省份 城市 購買數量 日期標籤
0 wifi365 叫我李2 2019-01-01 00:17:59 交易成功 186 6 上海 上海市 1 2019-01-01
1 wifi365 0cyb1992 2019-01-01 00:59:54 交易成功 145 0 廣東省 廣州市 1 2019-01-01
2 wifi365 蘿污萌莉 2019-01-01 07:48:48 交易成功 194 8 山東省 東營市 1 2019-01-01
3 wifi365 重碎疊 2019-01-01 10:00:07 交易成功 197 0 江蘇省 南京市 1 2019-01-01
4 wifi365 iho_jann 2019-01-01 10:00:08 交易成功 168 0 廣東省 廣州市 1 2019-01-01
df.shape
(27791, 10)
# 把單個客戶一天中的訂單合併:看成是一次整體的交易
dup = df.groupby(['買家暱稱','日期標籤'])['付款日期'].count().reset_index()
dup.head()
買家暱稱 日期標籤 付款日期
0 .blue_ram 2019-02-04 1
1 .christiny 2019-01-29 1
2 .willn1 2019-01-11 1
3 .託託m 2019-01-11 1
4 0000妮 2019-06-28 1
# 對合並後的用戶統計頻數
f = dup.groupby('買家暱稱')['付款日期'].count().reset_index()
f.columns=['買家暱稱','F']
f.head()
買家暱稱 F
0 .blue_ram 1
1 .christiny 1
2 .willn1 1
3 .託託m 1
4 0000妮 1

M

df.head()
品牌名稱 買家暱稱 付款日期 訂單狀態 實付金額 郵費 省份 城市 購買數量 日期標籤
0 wifi365 叫我李2 2019-01-01 00:17:59 交易成功 186 6 上海 上海市 1 2019-01-01
1 wifi365 0cyb1992 2019-01-01 00:59:54 交易成功 145 0 廣東省 廣州市 1 2019-01-01
2 wifi365 蘿污萌莉 2019-01-01 07:48:48 交易成功 194 8 山東省 東營市 1 2019-01-01
3 wifi365 重碎疊 2019-01-01 10:00:07 交易成功 197 0 江蘇省 南京市 1 2019-01-01
4 wifi365 iho_jann 2019-01-01 10:00:08 交易成功 168 0 廣東省 廣州市 1 2019-01-01
# 總金額
sum_me = df.groupby('買家暱稱')['實付金額'].sum().reset_index()
sum_me.columns = ['買家暱稱','總支付金額']
# 基於F表進行合併,並計算用戶的平均支付金額
comb = pd.merge(sum_me,f,how='inner',on='買家暱稱')
comb['M'] = comb['總支付金額']/comb['F']
comb
買家暱稱 總支付金額 F M
0 .blue_ram 49 1 49.0
1 .christiny 183 1 183.0
2 .willn1 34 1 34.0
3 .託託m 37 1 37.0
4 0000妮 164 1 164.0
... ... ... ... ...
25414 龍火師 175 1 175.0
25415 龍魔鬼女 87 1 87.0
25416 龜mil寶 497 2 248.5
25417 !謝鵬逗逼? 137 1 137.0
25418 ~小邱~ 185 1 185.0

25419 rows × 4 columns

創建RFM屬性表

rfm = pd.merge(r,comb,on='買家暱稱',how='inner')
rfm = rfm[['買家暱稱','R','F','M']]
rfm
買家暱稱 R F M
0 .blue_ram 146 1 49.0
1 .christiny 152 1 183.0
2 .willn1 170 1 34.0
3 .託託m 170 1 37.0
4 0000妮 2 1 164.0
... ... ... ... ...
25414 龍火師 84 1 175.0
25415 龍魔鬼女 72 1 87.0
25416 龜mil寶 11 2 248.5
25417 !謝鵬逗逼? 24 1 137.0
25418 ~小邱~ 158 1 185.0

25419 rows × 4 columns

rfm[['R','F','M']].describe([0.01,0.25,0.5,0.9,0.99]).T
count mean std min 1% 25% 50% 90% 99% max
R 25419.0 97.120225 58.452032 0.0 2.0 37.0 105.0 170.0 170.0 180.0
F 25419.0 1.077580 0.303221 1.0 1.0 1.0 1.0 1.0 2.0 7.0
M 25419.0 128.157942 75.858900 30.0 30.0 73.0 117.0 233.0 272.0 4647.0

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Fiqmb1AF-1589444596669)(attachment:%E5%9B%BE%E7%89%87.png)]

rfm.F.value_counts()
1    23668
2     1559
3      169
4       19
5        3
7        1
Name: F, dtype: int64

維度打分

# R : 設置爲30天一個維度,0-30:5,30-60:4,60-90:3,90-120:2,120以上:1 
rfm['R-score'] = pd.cut(rfm['R'], bins=[0,30,60,90,120,1000000],labels=[5,4,3,2,1],right=False).astype(float)
rfm.head()
買家暱稱 R F M R-score
0 .blue_ram 146 1 49.0 1.0
1 .christiny 152 1 183.0 1.0
2 .willn1 170 1 34.0 1.0
3 .託託m 170 1 37.0 1.0
4 0000妮 2 1 164.0 5.0
# F: 1,2,3,4,5,1000000
rfm['F-score'] =  pd.cut(rfm['F'], bins=[1,2,3,4,5,1000000],labels=[1,2,3,4,5],right=False).astype(float)
# M:0,50,100,150,200,1000000
rfm['M-score']= pd.cut(rfm['M'], bins=[0,50,100,150,200,1000000],labels=[1,2,3,4,5],right=False).astype(float)
rfm.head()
買家暱稱 R F M R-score F-score M-score
0 .blue_ram 146 1 49.0 1.0 1.0 1.0
1 .christiny 152 1 183.0 1.0 1.0 4.0
2 .willn1 170 1 34.0 1.0 1.0 1.0
3 .託託m 170 1 37.0 1.0 1.0 1.0
4 0000妮 2 1 164.0 5.0 1.0 4.0

第二輪打分:和平均值做比較

rfm['R是否大於均值'] = (rfm['R-score']>rfm['R-score'].mean())*1
rfm['F是否大於均值'] = (rfm['F-score']>rfm['F-score'].mean())*1
rfm['M是否大於均值'] = (rfm['M-score']>rfm['M-score'].mean())*1
rfm
買家暱稱 R F M R-score F-score M-score R是否大於均值 F是否大於均值 M是否大於均值
0 .blue_ram 146 1 49.0 1.0 1.0 1.0 0 0 0
1 .christiny 152 1 183.0 1.0 1.0 4.0 0 0 1
2 .willn1 170 1 34.0 1.0 1.0 1.0 0 0 0
3 .託託m 170 1 37.0 1.0 1.0 1.0 0 0 0
4 0000妮 2 1 164.0 5.0 1.0 4.0 1 0 1
... ... ... ... ... ... ... ... ... ... ...
25414 龍火師 84 1 175.0 3.0 1.0 4.0 1 0 1
25415 龍魔鬼女 72 1 87.0 3.0 1.0 2.0 1 0 0
25416 龜mil寶 11 2 248.5 5.0 2.0 5.0 1 1 1
25417 !謝鵬逗逼? 24 1 137.0 5.0 1.0 3.0 1 0 1
25418 ~小邱~ 158 1 185.0 1.0 1.0 4.0 0 0 1

25419 rows × 10 columns

客戶分層

rfm['人羣數值'] = rfm['R是否大於均值']*100+rfm['F是否大於均值']*10+rfm['M是否大於均值']
rfm
買家暱稱 R F M R-score F-score M-score R是否大於均值 F是否大於均值 M是否大於均值 人羣數值
0 .blue_ram 146 1 49.0 1.0 1.0 1.0 0 0 0 0
1 .christiny 152 1 183.0 1.0 1.0 4.0 0 0 1 1
2 .willn1 170 1 34.0 1.0 1.0 1.0 0 0 0 0
3 .託託m 170 1 37.0 1.0 1.0 1.0 0 0 0 0
4 0000妮 2 1 164.0 5.0 1.0 4.0 1 0 1 101
... ... ... ... ... ... ... ... ... ... ... ...
25414 龍火師 84 1 175.0 3.0 1.0 4.0 1 0 1 101
25415 龍魔鬼女 72 1 87.0 3.0 1.0 2.0 1 0 0 100
25416 龜mil寶 11 2 248.5 5.0 2.0 5.0 1 1 1 111
25417 !謝鵬逗逼? 24 1 137.0 5.0 1.0 3.0 1 0 1 101
25418 ~小邱~ 158 1 185.0 1.0 1.0 4.0 0 0 1 1

25419 rows × 11 columns

基於人羣數值給客戶打標籤

rfm['人羣類型'] = rfm['人羣數值'].map({
                                    111: '重要價值客戶',
                                    11: '重要召回客戶',
                                    101: "重要發展客戶",
                                    1: "重要挽留客戶",
                                    110: '潛力客戶',
                                    100: '新客戶',
                                    10: '一般客戶',
                                    0: '流失客戶'
                                })
rfm.head()
買家暱稱 R F M R-score F-score M-score R是否大於均值 F是否大於均值 M是否大於均值 人羣數值 人羣類型
0 .blue_ram 146 1 49.0 1.0 1.0 1.0 0 0 0 0 流失客戶
1 .christiny 152 1 183.0 1.0 1.0 4.0 0 0 1 1 重要挽留客戶
2 .willn1 170 1 34.0 1.0 1.0 1.0 0 0 0 0 流失客戶
3 .託託m 170 1 37.0 1.0 1.0 1.0 0 0 0 0 流失客戶
4 0000妮 2 1 164.0 5.0 1.0 4.0 1 0 1 101 重要發展客戶

統計描述並可視化

描述統計

count = rfm['人羣類型'].value_counts().reset_index()
count.columns = ['客戶類型','人數']
count['人數佔比'] = count['人數']/count['人數'].sum()
count
客戶類型 人數 人數佔比
0 重要挽留客戶 7336 0.288603
1 流失客戶 6681 0.262835
2 重要發展客戶 5427 0.213502
3 新客戶 4224 0.166175
4 重要價值客戶 756 0.029742
5 潛力客戶 450 0.017703
6 重要召回客戶 360 0.014163
7 一般客戶 185 0.007278
rfm['購買總金額'] = rfm['F']*rfm['M']
rfm.head()
買家暱稱 R F M R-score F-score M-score R是否大於均值 F是否大於均值 M是否大於均值 人羣數值 人羣類型 購買總金額
0 .blue_ram 146 1 49.0 1.0 1.0 1.0 0 0 0 0 流失客戶 49.0
1 .christiny 152 1 183.0 1.0 1.0 4.0 0 0 1 1 重要挽留客戶 183.0
2 .willn1 170 1 34.0 1.0 1.0 1.0 0 0 0 0 流失客戶 34.0
3 .託託m 170 1 37.0 1.0 1.0 1.0 0 0 0 0 流失客戶 37.0
4 0000妮 2 1 164.0 5.0 1.0 4.0 1 0 1 101 重要發展客戶 164.0
m = rfm.groupby('人羣類型')['購買總金額'].sum().reset_index()
m.columns = ['客戶類型','消費金額']
m['金額佔比'] = mon['消費金額']/mon['消費金額'].sum()
m
客戶類型 消費金額 金額佔比
0 一般客戶 25803.0 0.007349
1 新客戶 270869.0 0.077146
2 流失客戶 444679.0 0.126649
3 潛力客戶 64075.0 0.018249
4 重要價值客戶 269230.0 0.076679
5 重要發展客戶 981893.0 0.279652
6 重要召回客戶 116665.0 0.033227
7 重要挽留客戶 1337906.0 0.381048

可視化

result = pd.merge(count,m,on='客戶類型')
result.head()
客戶類型 人數 人數佔比 消費金額 金額佔比
0 重要挽留客戶 7336 0.288603 1337906.0 0.381048
1 流失客戶 6681 0.262835 444679.0 0.126649
2 重要發展客戶 5427 0.213502 981893.0 0.279652
3 新客戶 4224 0.166175 270869.0 0.077146
4 重要價值客戶 756 0.029742 269230.0 0.076679
plt.bar(result['客戶類型'],result['人數佔比'])
plt.plot(result['客戶類型'],result['金額佔比'],'yo-');

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章