RFM分析英國電商購物顧客羣體(KAGGLE)

實驗背景:

這是從2010/01/12-2011/12/09一家在英國的網絡電商的真實數據,所以數據類型和值都具有很強的隨機性,實踐性較強。

該電商的主營業務是賣一些訂製禮物。所以本次分析的目的是對該電商的客戶進行分類,以讓業務部門可以對不同的顧客有不一樣的促銷方式(marketing initiatives or offer),以增大銷量。

實驗內容:

數據預處理:

1.導入觀察數據:

#import all necessary package
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")

數據源:https://www.kaggle.com/carrie1/ecommerce-data

#load data
df=pd.read_csv(r'E:\test\ecommerce-data\data.csv',encoding='ISO-8859-1')
df.head()

在這裏插入圖片描述
觀察數據一共有8列,根據已經顯示的前5列,發現數據特點是同一個顧客ID可能在同一個INVOCE中購買了多項商品,並且逐行顯示。

2.清理數據:

#觀察數據
df.info()

在這裏插入圖片描述
重點關注InvoiceDate 是object格式,爲了之後方便計算,我們最好將其變換爲Datetime的格式。

#利用Datetime函數,加入指定格式,識別參數
df['InvoiceDate']=pd.to_datetime(df.InvoiceDate,format='%m/%d/%Y %H:%M')

3.檢查空值

df.isnull().sum()

在這裏插入圖片描述
可以看到CID有相當多的空值,由於剛剛沒有顯示空值行的屬性,現在單獨將其列出進行分析:

Nan_rows=df[df.isnull().T.any()]
Nan_rows.tail(5)

在這裏插入圖片描述
因爲我們無法通過別的列進行推斷或者根據已有數據進行插值法補全CID,所以將其歸類爲髒數據刪除

df=df.dropna(subset=['CustomerID'])
df.isnull().sum()

在這裏插入圖片描述
當我們刪除CID之後,Description也爲0。說明之前的那些CID爲NaN的行裏有一部分的Description也爲NaN

4.重複值檢查

df.duplicated().sum()

在這裏插入圖片描述
重複值只有5000多行,影響不大,我們選擇刪除

df.drop_duplicates(inplace=True)

在數據已經被清理乾淨之後,我們可以對其特徵進行觀察

數據分析與觀察

1:找出Country一共有幾種:

df.Country.unique()

在這裏插入圖片描述
顧客來自很多國家,那具體的下單數量和國家有很大的關聯嗎?我們可以將每個國家的下單數量進行排序並且可視化進行分析:

#先要將重複的CID去除,保證一個顧客只被計算了一次
order_unique_cus=df.drop_duplicates(['CustomerID'], keep='first', inplace=False)
order_sum=order_unique_cus.groupby(by='Country').UnitPrice.count()
order_sum=order_sum.sort_values(ascending=False).head(5)
plt.figure(figsize=(20,5))
sns.barplot(order_sum.index,order_sum.values,palette="Greens_r")
plt.ylabel('Counts')
plt.title('Num of orders in different country',fontsize=15,color='r',fontweight='bold')
plt.xticks(rotation=45)

在這裏插入圖片描述
明顯的可以觀察等到英國的購買人數佔主要消費,計算出佔比爲:

order_unique_cus.loc[order_unique_cut.Country=='United Kingdom'].shape[0]/order_unique_cut.shape[0

在這裏插入圖片描述
綜上,由於主要消費羣體爲英國,並且每個國家的用戶購買習慣也不一樣,之後的RFM分析將只會針對英國的顧客進行分析

df.describe()

在這裏插入圖片描述我們可以看到QUANTITY和Unitprice都有極大值的影響,圖像應該是嚴重的長尾狀態。
並且發現QUANTITY裏竟然有負數的出現,將這些負數取出進行觀察:

#option1:
df[df['Quantity']<0].head(5)
#option2:
df1=df.query("Quantity<0").head(5)

在這裏插入圖片描述
發現Q爲負數的時候,InvoiceNo前面都有C的出現,經過確認C開頭意味着取消的訂單。

還有一種情況就是Stockcode爲D的時候,後面都註釋該商品爲打折商品

這些數據對我們造成了很大的困擾, 因爲被取消,造成的原因很多,例如拍錯或者不想要等原因, 這個可以之後在關注流失的時候重點分析,我們現在可以將他們先行取消。

#用DROP,刪除掉<0的行(以Index爲索引)
df.drop(df[ df.Quantity<0].index, inplace=True)
df.describe()

在這裏插入圖片描述

現在數據已經基本上徹底“乾淨”,我們可以開始進行RFM分析:

英國顧客的RFM分析

首先我們選擇以天數爲最小時間單位,創建新的一列date:

import datetime
df['date']=df['InvoiceDate'].apply(lambda x: x.date)

在這裏插入圖片描述
DATE一列已經被創造出來,且我們保存了原來的InvoiceDate 方便之後進行對照,RFM的定義不再贅述,下面是針對該實驗的每個參數的實現方法:

R:最近的一次的消費。我們採用最後一天(max)作爲“今天”減去每位顧客最後一次消費的時間

F: 每位顧客購買的頻次

M:每位顧客購買的銷量總額: unitprice*quantity

#創建消費總額列
df['M']=df['UnitPrice']*df['Quantity']
#將需要分析的列提出,創建一個RFM數據透視表
rfm=pivot_table(index='CustmerID',values=['date','InvoiceNo','M'],aggfunc=['date':'max','InvoiceNo':'count','M':'sum'])
#將Invoice的列名修改成F 
rfm.rename(columns={'Invoice':'F'},inplace=True)
#計算最近一次消費,並且將結果類型換算成可計算的數據類型
rfm['R']=(rfm.date.max()-rfm.date)/np.timedelta64(1,'D')
#再次取出需要分析的3列
rfm1=rfm[['R','F','M']]
rfm1

在這裏插入圖片描述
接下來,我們用**聚類(KMEANS)**進行RFM分析:

聚類裏有一個重要的參數是K,也就是我們將數據分爲幾類是最合適的。這個會有欠擬合和過擬合的問題,所以K的選擇至關重要。本次選用手肘法進行評測:

手肘法的核心就是觀察SSE(誤差平方和),當你分類越多,樣本劃分就越來越精細,SSE自然會逐漸減小,但當K增大到一定程度時,對結果的影響就不會很大。所以我們畫出分類從1至10,看SSE的變化趨勢,選出拐點處對應的類數。

#我們選擇1-10 ,對每一個都進行評估
SSE=[]
for k in range(1,10):
	estimator=Kmeans(n_cluster=k)
	estimator.fit(rfm1)
	SSE.append(estimator.inertia_)
x=range(1,10)
plt.plot(x,SSE,'x-')
plt.show()

在這裏插入圖片描述
當K=3的時候,會獲得最好的分類,接下來我們就可以使用kmeans包進行計算

#選用3作爲合適的簇,進行擬合
kmeans=KMeans(n=cluster=3,random_state=0.fit(rfm1)
#獲取每個點的label
rfm1['cluster']=kmeans.labels_
rfm1.sort_values(by='cluster')

在這裏插入圖片描述

看到所有顧客已經被分爲3類,我們接着探究一下每類的特性

R & Cluster

sns.boxyplot(rfm1.cluaster,rfm.R)
plt.title('boxplot across R and Cluster',fontsize=15,color='r',fontweight='bold')
plt.savefig(r'E:\test\ecommerce-data\boxplot across R and cluster.png')

在這裏插入圖片描述
首先因爲R代表的最近的一次消費,所以需要R越小越好,根據箱線分佈圖:

  1. 第一類的客戶分佈較廣,極值過高,爲“最差”表現
  2. 第三類除了一些異常值的出現,它的極大值相比於第二類也比較高。
  3. 第二類的表現最好,極值中位數平均數全部都是最低水平,屬於我們的“黃金VIP”

從R分析顧客的等極度爲: 2>3>1

F & Cluster

sns.boxplot(rfm1.cluster,rfm1.F)
plt.title('boxplot across F and Cluster',fontsize=15,color='r',fontweight='bold')
plt.savefig(r'E:\test\ecommerce-data\boxplot across F and cluster.png')

在這裏插入圖片描述
由於F代表頻數,我們希望F越大越好,說明買的次數多,根據箱線分佈圖:

  1. 第一類的客戶雖有個別極值,但是普遍中位數包括平均數都較低,表現依舊不太樂觀。
  2. 第二類屬於中間水平,表現中等。
  3. 第三類的表現最好,不僅極大值多,中位數平均數全部都是最高水平,說以他們依然佔據着“黃金VIP”席位

從F分析顧客的等極度爲: 3>2>1

M & Cluster

sns.boxplot(rfm1.cluster,rfm1.M)
plt.title('boxplot across M and Cluster',fontsize=15,color='r',fontweight='bold')
plt.savefig(r'E:\test\ecommerce-data\boxplot across M and cluster.png')

在這裏插入圖片描述
最後M也是商家最在乎的消費總金額,越高買的金額數越大,商家就越獲利,根據箱線分佈圖:

  1. 第一類的客戶依舊最低值。
  2. 第三類屬於中間水平,消費普遍在5萬至10萬之間。
  3. 第二類的表現是最驚人的,他也應該是在之前我們分析數據時,極值的所在處,中位數都已經快接近20萬

從M分析顧客的等極度爲: 2>3>1

綜上: 可以得到第二類是最需要保值的顧客,我們可以將他們列爲我們的“黃金VIP”提高留存。第三類其次,第一類則爲相對遜色的普通用戶。

然而,在聚類中,我們只分了三大類。

根據業務要求,如果想參照經典的RFM將每個指標都分類劃分,目的也是能根據更精細劃分來增強營銷的精準性,則會採用另外一種編程方法實現。

當然,具體對於每一個指標劃分點在現實工作中要和業務進行討論,如果在沒有經驗數據的基礎上,用分位數函數進行分組就是最科學的。

我的方法是先定義2個不同的函數,因爲3個參數的中需要R越低越好,而F和M則是最高越好。

#在每一次新的計算,我偏向於創建一個變量,這樣保證原始文件的完整性。
rfm2=rfm[['R','F','M']]
#將原始的RFM數據分爲4等分
quantile=rfm2.quantile(q=[0.25,0.5,0.75])
def Rscore(x,col):
	if x<=quantile[col][0.25]:
	return 1
	elif x<=quantile[col][0.5]:
	return 2
	elif x<=quantile[col][0.75]:
	return 3
	else:
	return 4


def FMScore(x.col):
	if x<=quantile[col][0.25]:
	return 4
	elif x<=quantile[col][0.5]:
	return 3
	elif x<=quantile[col][0.75]:
	return 2
	else:
	return 1

接下來,將函數運用在rfm中:

rfm2['Rscore']=rfm2['R'].apply(Rscore,args=('R'))
rfm2['f_score']=rfm2['F'].apply(FMscore,args=('F'))
rfm2['m_score']=rfm2['M'].apply(FMscore,args=('M'))

在這裏插入圖片描述

這時,有2種方法:

第一種爲直接合並法:1+1+1=111 然後確定分類

第二種是將每組的得分利用權重相加:

本次分析採用第二種,但是將第一種的實現寫在下面:

#直接合並法:因爲rfm爲數值型變量,我們需要將他們變爲字符串相加
rfm2['str_score']=rfm2['r_score'].apply(str)+rfm2['f_score'].apply(str)+rfm2['m_score'].apply(str)


#或者用map直接對每一列的數值一一映射成爲STR

rfm2['rfmscore']=rfm2['r_score'].map(str)+rfm2['f_score'].map(str)+rfm2['m_score'].map(str)

第二種的權重法:

#我將M的權重設爲0.5爲最重要,R設爲0.2,F設爲0.3
rfm2['rfm_total_score']=rfm2['r_score']*0.2+rfm2['f_score']*0.3+rfm2['m_score']*0.5

得到下圖:
在這裏插入圖片描述
得到得分後,我們對每一個等級的顧客進行貼標籤化:

bins=rfm2['rfm_total_score'].quantile(q=[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1])
bins[0] =0
labels =  ['流失客戶','一般維持客戶','一般發展客戶','潛力客戶','重要挽留客戶','重要保持客戶','重要發展客戶','重要價值客戶']
rfm2['level'] = pd.cut(rfm2.rfm_total_score,bins,labels=labels)

在這裏插入圖片描述
可視化:

#這塊是爲保證可視化輸出 中文不是小方塊的問題
import matplotlib.pyplot as plt  
plt.rcParams['font.sans-serif'] = [u'SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(15,8))
#準備好要可視化的表格
cus=rfm2.groupby('level').count().sort_values('R')
x=cus.index
y=cus.R
#畫圖修飾
plt.bar(x,y,alpha=0.9, facecolor = 'lightskyblue', edgecolor = 'white')
plt.xticks(x,rotation=60,fontsize=15)
plt.title('The Number Of Customer \n In Different Type',fontsize=20,color='r',fontweight='bold')
plt.ylabel('Num of Customer',fontsize=15)
plt.xlabel('Level',fontsize=15)
plt.savefig(r'E:\test\ecommerce-data\The number of customer in different type.png')

在這裏插入圖片描述
從這個可以看到重要發展客戶佔絕大多數,說明該電商的前景還是很樂觀的,可以在保證重要價值客戶依舊留存的基礎上,加大營銷力度等,將更多的重要發展客戶變爲忠誠客戶,擴展業務。

實驗結果

我們分別利用了聚類和分箱的方式,實現了RFM顧客分層,結合業務後,提出了對於營銷的一些意見。並且由於此數據量的類型非常全面,之後我們也可以去從不同的維度分析該公司情況,包括用更多的算法來測試哪一個參數對總銷售額的影響最大,以更完備的提供一些可實用性建議和意見。

PS:這是我寫的第二篇數據分析的報告,如果大家發現有錯誤歡迎評論區留言,這樣可以互相進步!如果沒有歡迎大家點贊給個鼓勵!嘿嘿

下面的鏈接是我第一篇處女座數據分析報告,主要是針對2019年airbnb紐約的房源進行的可視化一些練習,也歡迎大家移步去看看。(十二賣瓜,自賣自誇,哈哈):
https://blog.csdn.net/MRmaand12/article/details/105788430

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