【Python 商學院】使用 Python 進行 RFM分析 — 顧客分類好工具

前言

在現今行銷科學的領域當中,一間公司若能知道他的顧客類型,在行銷上是非常有效率的事情,所以我們去各大賣場購物時,常常會遇到店員對你推薦加入該賣場的會員,因為透過會員卡他們可以記錄你的購物頻率、時間、金額、品項,這些資料對於賣場而言是非常有幫助的,除了可以了解自家賣場的顧客類型,還可以藉此讓他們針對不同類型的顧客提出不同的行銷方案,進而提高賣場的營業額,還能降低行銷成本。本篇文章將參考此篇 Kaggle文章 – Customer Segmentation using RFM Analysis 的內容,提供完整的RFM模型程式碼,並進行解說,讓我們能使用這個簡單強大的工具。

RFM模型介紹

在進行 RFM 模型的分析前,我們首先對 RFM 進行介紹,RFM 模型由George Cullinan於1961年提出,採用消費資料的三大指標,最近一次消費(Recency)、消費頻率(Frequency)、與消費金額(Monetary),三大指標的英文開頭分別為R、F、M,所以就稱為「RFM模型」,由於如果只用單一指標對顧客進行分類可能不夠全面,因此RFM模型有一個很大的優勢是平衡三項指標,對於顧客類型提供更客觀的分析。

(1) 最近一次消費R (Recency): 指消費者至今與上次購買產品的時間間隔,如果時間間隔越短代表最近這個顧客的消費狀態活躍,給予較高的分數。

(2) 消費頻率F (Frequency): 指消費者在一定期間內至賣場購物的次數,次數越多者給予較高的分數。

(3) 消費金额M (Monetary): 指消費者在一定期間內至賣場購物的總金額,總金額越高給予較高的分數。

然而分數的給予是一個值得探討的問題,因為我們如果每個指標給1-5分,這樣就會有125種分類的顧客,這樣可能將顧客切分得太細,然而如果只給1-2分,切分出來的顧客類型只有8種,無法完全反映顧客類型,因此本文將每個類型給予4分,因此會形成64種顧客類型,然而還是要視資料樣本大小而定,如果樣本數量夠高,給到5分以上也可以考量,至於給分方式會在後面程式碼的部分,詳細說明。

RFM分析

import pandas as pd
df=pd.read_csv('Online Retail.csv',encoding = "ISO-8859-1")
df.head()

首先先載入Pandas套件,在讀取資料檔案,然而在這個檔案當中要透過”ISO-8859-1″的編碼方式才能讀取,因此加入encoding這個參數,最後顯示這份資料的前五行。

df.shape

此份資料有541909筆,並且有8欄資料。

df.isnull().sum()

查看這份資料是否有遺漏值,在Description與CustomerID這兩欄資料當中有遺漏值,因此我們必須對遺漏值做處理。

df=df.dropna()
df.shape

使用dropna()函數將所有遺漏值的資料都刪除,再檢視一次資料,此時資料只剩406829筆。

df['InvoiceDate'] = pd.to_datetime(df['InvoiceDate'], format = "%d-%m-%Y %H:%M")
df.head()

我們將InvoiceDate此欄資料透過pd.to_datetime()函數將其資料型態改成日期型態,並改變其時間格式,方便後續的分析,

M: 消費金額(Monetary)分析

df["Amount"]  = df['Quantity'] * df['UnitPrice']
monetary = df.groupby("CustomerID")['Amount'].sum()
monetary = monetary.reset_index()
monetary.head()

先創造一個新欄位”Amount”,將數量與物品單價相乘得出金額,再使用groupby()函數,根據各顧客號碼,將其過去所有的購物金額進行加總,並創造一個monetary表格,重新產生索引值。

F: 消費頻率(Frequency)分析

frequency = df.groupby("CustomerID")['InvoiceNo'].count()
frequency = frequency.reset_index()
frequency.head()

消費頻率的部分,這裡採用根據各顧客的不同發票數量次數,作為消費頻率的指標,每一張發票就當作消費一次,因此InvoiceNo此欄資料在本分析是相當實用的數據,並創造一個frequency表格,重新產生索引值。

fm = monetary.merge(frequency, on = "CustomerID", how = "inner")
fm.head()

將上述monetary、frequency兩個表格,根據CustomerID進行合併,因為我們是分析顧客類型,因此根據顧客號碼合併。

R: 最近一次購物 (Recency) 分析

maximum = max(df.InvoiceDate)
maximum = maximum + pd.DateOffset(days = 1)
df['day_diff'] = maximum - df['InvoiceDate']
df.head()

先找出所有購物日期當中最大的一天當作基準點,再把那一天日期加上一天,此資料最大的一天是”2011-12-09″,加上一天後基準變為”2011-12-10″,再算出時間間隔,舉例而言如果有一張發票的日期是”2011-11-30″,用”2011-12-10″ – “2011-11-30” ,此筆資料的”day_diff”為10。

recency = df.groupby('CustomerID')['day_diff'].min()
recency = recency.reset_index()
recency.head()

根據各顧客的”day_diff”資料當中取出最小值,作為該顧客最近一次購物的指標,並創造一個recency表格,重新產生索引值。

RFM = fm.merge(recency, on = "CustomerID")
RFM.columns = ['CustomerID','Amount','Frequency','Recency']
RFM.head()

將recency表格與fm表格進行合併,產生新的RFM表格,並重新命名欄位名字

進行RFM分析

RFM_norm1 = RFM.drop("CustomerID", axis=1)
RFM_norm1.Recency = RFM_norm1.Recency.dt.days
RFM_norm1.head()

創造一個新的表格並刪除”CustomerID”欄位,再用dt函數將Recency當中的天數取出。

quantiles = RFM_norm1.quantile(q=[0.25,0.5,0.75])

接著將每一個欄位分成四等分,前面有提到我們會給予每欄資料分數,這裡是根據四分位數將各欄切成四等分,如果你是要切成五等分將 q 改成 [0.2,0.4,0.6,0.8] 即可。

def R_Class(x,p,d):
    if x <= d[p][0.25]:
        return 4
 elif x <= d[p][0.50]:
        return 3
    elif x <= d[p][0.75]: 
        return 2
    else:
        return 1

定義Recency的分數,由於最近一次的購物天數如果越短代表此顧客對於賣場價值越大,因此給於較高的分數,所以在第一四分位以內的天數資料,給予4分,第三四分位數後的資料給予1分。

def FM_Class(x,p,d):
    if x <= d[p][0.25]:
        return 1
    elif x <= d[p][0.50]:
        return 2
    elif x <= d[p][0.75]: 
        return 3
    else:
        return 4

定義Frequency、Monetary的分數,由於頻率越高或金額越高代表此顧客對於賣場的價值越大,因此給於較高的分數,所以在第三四分位以後的天數資料,給予4分,第一四分位數內的資料給予1分,此兩個指標與前述指標給分標準剛好相反。

RFM_Segment = RFM_norm1.copy()
RFM_Segment['R_Quartile'] = RFM_Segment['Recency'].apply(R_Class, args=('Recency',quantiles,))
RFM_Segment['F_Quartile'] = RFM_Segment['Frequency'].apply(FM_Class, args=('Frequency',quantiles,))
RFM_Segment['M_Quartile'] = RFM_Segment['Amount'].apply(FM_Class, args=('Amount',quantiles,))

先複製一個新的RFM_Segment表格,再根據 “Recency”、”Frequency”、”Monetary”,三欄資料根據前述的給分定義計算出各自在R、F、M的分數。

RFM_Segment['RFMClass'] = RFM_Segment.R_Quartile.map(str) \
                            + RFM_Segment.F_Quartile.map(str) \
                            + RFM_Segment.M_Quartile.map(str)

最後將RFM三欄的分數變成字串,形成新的欄位,對於賣場最有價值的顧客其分類代號為”444″,最沒有價值的顧客其分類代號為”111″,如此一來就完成RFM模型的分析了。

len(RFM_Segment[RFM_Segment['RFMClass']== '444'])/len(RFM_Segment)

最後我們看顧客分類代號為 “444” 的黃金顧客佔全部顧客的比例,高達10%,由此可知此賣場有10%的顧客是死忠顧客。

結論

本文章介紹RFM模型的基本概念與如何使用Python進行RFM模型分析,此工具對於商學院的學生是一個簡單又好用的模型,跟其他顧客分群的方式相比,不用懂機器學習也能使用,然而分析顧客分類後的行銷方案才是重點,因此除了分析的能力外,也要結合商業的理論,推出後面的行銷方案,才能將分析結果發揮最大的效用,希望此篇文章能幫助觀看的你,感謝觀閱,也歡迎留言,讓我們知道這篇文章是否幫助到你。



作者:TKH

企業管理學碩士,對 Python、資料科學有滿滿的熱忱,就讀碩士期間開始學習程式語言、機器學習,並於碩士論文使用深度學習 LSTM 進行股價預測。

本文作者TKH為企業管理學碩士,對 Python、資料科學有滿滿的熱忱,就

留言討論區