k-means與RFM模型結合進行用戶群體劃分

RFM是什么

在CRM系統中經常要對用戶進行劃分,以標記不同的標簽,進行個性化的營銷觸達動作。通常的用戶群體劃分會使用用戶的一些屬性信息,例如年齡,職業,性別等。但是這些屬性基本上都是用戶本身的特征屬性,并不是和品牌關聯產生的屬性信息。另外一種常用的用戶模型,就是RFM模型,是以用戶的實際購買行為數據作為基礎,進行用戶群體的劃分的,在實踐中更加具有實際價值。

RFM模型由三個指標組成,分別為:

最近一次消費 (Recency)

消費頻率 (Frequency)

消費金額 (Monetary)

可以看到這三個屬性都是通過用戶的購買行為計算得出的,這些指標基本上代表了用戶是否活躍,購買能力,忠誠度等信息。

而我們的目標是通過對每個用戶的RFM屬性進行計算,將用戶群體劃分為不同的種類進行區分,以便我們進行分析和精準營銷。例如我們可以分析出高價值用戶,重點發展用戶,流失用戶等群體進行針對性營銷動作。

rfmModel.png

本文將使用Python的一些工具包,對用戶數據集進行分析處理,例如建立RFM模型,數據標準化,以及使用k-means聚類算法將用戶群體進行劃分。需要讀者具有一些基礎的Python和數據統計知識。

通過數據建立RFM模型

首先我們通過一些訂單數據分析得到一部分用戶的樣本數據來:

user_id,total_order_count,total_order_price,last_order_date
161526959,1,11878,2017-07-13 19:22:43.0
38972904,1,20735,2017-08-11 00:51:06.0
136664518,1,12680,2017-02-26 10:48:20.0
3921846,3,24722,2017-08-17 23:31:49.0
103291929,6,218720,2018-02-12 14:17:54.0
71742617,1,8919,2018-01-10 00:57:43.0
15114544,1,2935,2017-02-17 15:57:25.0
......

這里包括了用戶的id,總購買筆數,總購買金額以及最后一筆訂單時間的信息。我們將文件加載進來,截取一部分后對字段類型進行處理:

import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

df = pd.read_csv('./membersData.csv')
df = df.drop(df.index[5000:])
df['last_order_date'] =  pd.to_datetime(df['last_order_date'])

為了將其轉化為我們要使用的RFM屬性,我們需要對last_order_date進行處理,轉換為最后一次訂單時間到目前的天數。這樣我們就獲得了RFM的基本屬性,分別為last_order_day_from_now(R), total_order_count(F), total_order_price(M)。處理完成后對數據進行可視化觀察數據分布:

df['last_order_day_from_now'] = (pd.to_datetime('today') \
  - df['last_order_date']).dt.days

df.plot.scatter(x='last_order_day_from_now', 
                y='total_order_count', 
                c='total_order_price',
                cmap='viridis_r', s=50);

其散點圖為:


step1.png

我們會發現實際上的數據大部分都聚集在了一起,并且有一些非常離散的極端值數據,這對我們后續進行數據聚類會產生不利影響,所以我們使用log函數對數據進行處理,讓其分布的更加均勻:

df['total_order_count_log'] = np.log10(df['total_order_count'])
df['total_order_price_log'] = np.log10(df['total_order_price'])
df['last_order_day_from_now_log'] = np.log10(
        df['last_order_day_from_now'])

df.plot.scatter(x='last_order_day_from_now_log', 
                y='total_order_count_log', 
                c='total_order_price_log',
                cmap='viridis_r', s=50);
step2.png

可以看到現在數據分布的已經比較均勻了,這為我們進行聚類打下一個比較好的基礎。但同時我們也會發現RFM這三個屬性的單位卻并不相同,分別是天數,交易筆數和交易金額。這就造成了其數值差別巨大。而聚類算法一般都是使用不同向量間的距離進行計算劃分的,屬性單位不同造成的數值差異過大會造成計算距離時的權重分布不均衡,也并不能反映實際情況,所以我們還要對數據進行標準化處理,這里我們使用z-score對RFM屬性進行加工運算。
z-score是一種數據標準化的計算方法,其公式為:
z = (x – μ) / σ
μ代表x所屬數據組的平均值,σ代表x所屬數據組的方差。所以通過z-score計算,我們將絕對值數據轉化為一個數據在所屬數據組中的位置(得分),這樣不同單位和類型間的數據使用z-score做相互的比較也就有了一定的意義。

df['total_order_count_zscore'] = stats.zscore(df['total_order_count_log'])
df['total_order_price_zscore'] = stats.zscore(df['total_order_price_log'])
df['last_order_day_from_now_zscore'] = stats.zscore(
        df['last_order_day_from_now_log'])

df.plot.scatter(x='last_order_day_from_now_zscore', 
                y='total_order_count_zscore', 
                c='total_order_price_zscore',
                cmap='viridis_r', s=50);
step3.png

這時候會看到數據不但分布較為均勻,而且不同維度間的數值差異也很小了,這樣我們可以把三種不同單位的屬性一起進行處理。

基于RFM模型對用戶數據進行分類

當我們建立好RFM的數據模型之后,期望通過不同的RFM值,對用戶進行區分以進行精準化營銷。當然我們可以通過對RFM這三組數值的平均值或者中位數和每個用戶進行比較,以建立起一個數據立方,進行群體劃分。但另外一方面,一般來說用戶群體會大致符合28原則,80%左右的收入是由20%左右的客戶所貢獻的,所以根據平均值或者中位數進行群體劃分也并不能總是科學的反應出不同的用戶群體來,所以我們也可以基于數據本身的特性,使用聚類算法進行處理,以便讓數據更加“自然”的區分。
這里我們選用非常常用的k-means算法進行聚類計算,k-means聚類的原理并不復雜,首先隨機的或者通過更高效的方式(例如k-means++)選取k個點,然后不斷迭代的計算,修正這k個點的坐標,目的是讓集合中的每個點的距離(有很多種距離算法,比較常用的是歐氏距離)都和k個點里的其中一個盡量的近,而和其他的盡量的遠。這樣數據集合就能根據自身的分布規律,自然的區分出不同的類別來。

from sklearn.cluster import KMeans

sampleArray = df.iloc[:,8:].values
kmeans = KMeans(n_clusters=3, random_state=0).fit(sampleArray)

df.plot.scatter(x='last_order_day_from_now_zscore', 
                y='total_order_count_zscore', 
                c=kmeans.labels_,
                cmap='viridis_r', 
                norm=None, s=50);

這里我們將k值設定為3,也就是將數據劃分為三個部分,通過使用我們處理后的RFM屬性進行計算,最終我們得到:

step4.png

可以看到不同的顏色代表不同的用戶類別,可以簡單的認為標記為0的是流失用戶,1是重點發展用戶,2是高價值用戶。這樣我們就可以對不同的群體使用適合的營銷策略了,同時當有新的用戶加入后,我們也可以使用得到的k-means模型對其進行預測劃分。

可能遇到的問題

在使用這種方式做實際的數據處理時,可能因為數據分布的原因導致區分度并不是特別好,因為根據銷售數據進行用戶區分,并不是總能發現比較明顯的區分“界限”,也就是不同群體間的邊界其實是非常模糊和混雜的(從上面的最終分析圖也可以看出這樣的情況),所以從這個角度講,單純通過RFM模型和聚類進行用戶群體劃分也是有它的局限性的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容