聚类分析|基于RFM模型对用户价值进行分析

数据大师
数据大师
数据大师
293
文章
0
评论
2021-09-0117:34:56 评论 33 9569字
摘要

本文基于RFM模型对用户价值进行分析

 

目录

文章分为以下五大部分

  • 项目介绍
  • 数据准备
  • 数据处理
  • 数据分析
  • 总结

一、项目介绍

在之前淘宝用户行为分析中,有用到RFM模型做分析,但因为数据集不涉及M信息,只利用RF做了分析,现在找到一个比较合适的数据集,对其进行完整的RFM分析,并利用无监督聚类算法中的代表K-Means进行进一步探究。

数据集为携程提供,携程作为中国领先的综合性旅行服务公司,每天向超过2.5亿会员提供全方位的旅行服务,在这海量的网站访问量中,我们可分析用户的行为数据来挖掘潜在的信息资源,进行用户画像,从而提供更好的运营服务和完善产品设计,提升用户体验。

二、数据准备

2.1数据集来源

网址:携程旅行网: 云海竞赛平台

数据集包括:训练集和测试集。训练集为2016.05.15-2016.05.21期间一周的访问数据,测试集为2016.05.22-2016.05.28期间一周的访问数据。本篇文章主要讨论的是聚类分析,所以只用训练集。

2.2字段描述

聚类分析|基于RFM模型对用户价值进行分析

三、数据处理

3.1导入数据

#导入基础包import pandas as pdimport numpy as npimport seaborn as snsimport matplotlib.pyplot as pltplt.rcParams["font.sans-serif"]=["SimHei"] #用来正常显示中文标签plt.rcParams["axes.unicode_minus"]=False #用来正常显示负号%matplotlib inline#读取数据df=pd.read_csv("C:/Users/dwhyx/Downloads/data/userlostprob_train.txt",sep="	")df.describe()
聚类分析|基于RFM模型对用户价值进行分析

3.2列值处理

聚类分析|基于RFM模型对用户价值进行分析

通过查看数据类型,发现所有字段中只有d、arrival两个字符串格式,分别代表预定时间和入住时间,都为yyyy-mm-dd日期形式,将其相减可得到"提前预定的天数",得到新的衍生变量特征。

# 转为日期型格式df["arrival"]=pd.to_datetime(df["arrival"])df["d"]=pd.to_datetime(df["d"])# 相减得到"提前预定天数"列df["day_advanced"]=(df["arrival"]-df["d"]).dt.days# 删除原有列df=df.drop(["d","arrival"],axis=1)

3.3异常值处理

通过描述统计观察发现,delta_price1、delta_price2、lowestprice、customer_value_profit、ctrip_profits这几个变量最小值为负值,需要对其处理。同时,结合四分位和极值,发现有极大或极小的异常值,如decisionhabit_user、historyvisit_avghotelnum等,较多字段都存在异常值,对所有字段一并进行处理。

for col in ["delta_price1","delta_price2","lowestprice"]:    df.loc[df[col]<0,col]=df[col].median()  # 填充中位数for col in ["customer_value_profit","ctrip_profits"]:    df.loc[df[col]<0,col]=0  # 填充0#极值处理for i in df.columns:    df.loc[df[i]<np.percentile(df[i],1),i]=np.percentile(df[i],1)    df.loc[df[i]>np.percentile(df[i],99),i]=np.percentile(df[i],99)

3.4缺失值处理

3.4.1缺失值删除

利用dropna(thresh=n)过滤方式,删除行列缺失值大于80%的数据。这里重点理解thresh参数的用法。

print("删除空值前数据维度是:{}".format(df.shape))df.dropna(axis=0,thresh=df.shape[1]*0.2,inplace=True)  df.dropna(axis=1,thresh=df.shape[0]*0.2,inplace=True)print("删除空值后数据维度是:{}".format(df.shape))
聚类分析|基于RFM模型对用户价值进行分析

3.4.2缺失值补充

对缺失值补充前,先查看一下各变量的数值分布。

df.hist(figsize=(20,20))plt.savefig("hist.png")
聚类分析|基于RFM模型对用户价值进行分析

通过上图看出"businessrate_pre","businessrate_pre2","cancelrate_pre","customereval_pre2 "这些字段大体服从正态分布,可以用均值填充;其余字段大都呈右偏态分布,右偏分布就不可以用均值填充了,因为会受到极值的影响,但中位数不太受异常值或者极值的影响,使用中位数填充比较合适。

filter_mean=["businessrate_pre","businessrate_pre2","cancelrate_pre","customereval_pre2 "]for i in df.columns:    if i in filter_mean:        df[i].fillna(df[i].mean(),inplace=True)    else:        df[i].fillna(df[i].median(),inplace=True)

3.5极值处理

通过上面数据描述分析,数据集中还存在极值,过大或者过小的值会对模型分析造成影响,这里通过截断填充的方式,分别对极小值和极大值进行处理。

for i in df.columns:    df.loc[df[i]<np.percentile(df[i],1),i]=np.percentile(df[i],1)   #小于1%分位数的用1%分位数填充    df.loc[df[i]>np.percentile(df[i],99),i]=np.percentile(df[i],99)  # 大于99%分位数的用99%分位数填充

四、数据分析

4.1指标选取

RFM模型是衡量客户价值和客户创利能力的重要工具和手段,其有三个指标:最近一次消费时间间隔(Recency),消费频率(Frequency),消费金额(Monetary)。本数据集中三个指标并不都是直接给出,需要进行分析提取。

  • Recency:选用lasthtlordergap(距离上次下单时长)此字段。
  • Frequency:选用ordernum_oneyear(用户年订单数)此字段。
  • Monetary:选用avgprice(平均价格),consuming_capacity(消费能力指数)这两个字段作为消费金额指标,合并为consume_level。
consume_level=["avgprice","consuming_capacity"]    # 合并字段作为消费水平from sklearn.decomposition import PCA   #利用PCA主成分分析无监督的降维方法pca=PCA(n_components=1)  #n_components设置为1df["consume_level"]=pca.fit_transform(df[consume_level])  #返回降维后的数据df.drop(consume_level,axis=1,inplace=True)  #删除冗余列

4.2RFM建模分析

#字段重名rfm = df[["lasthtlordergap","ordernum_oneyear","consume_level"]]  rfm.rename(columns={"lasthtlordergap":"recency","ordernum_oneyear":"frequency","consume_level":"monetary"},inplace=True)#利用MinMaxScaler进行归一化处理from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler()scaler.fit(rfm)rfm = pd.DataFrame(scaler.transform(rfm),columns=["recency","frequency","monetary"])#分箱rfm["R"]=pd.qcut(rfm["recency"], 2)rfm["F"]=pd.qcut(rfm["frequency"], 2)rfm["M"]=pd.qcut(rfm["monetary"], 2)# 根据分箱情况进行编码,二分类可以直接用标签编码方式from sklearn.preprocessing import LabelEncoderrfm["R"]=LabelEncoder().fit(rfm["R"]).transform(rfm["R"])  rfm["F"]=LabelEncoder().fit(rfm["F"]).transform(rfm["F"])rfm["M"]=LabelEncoder().fit(rfm["M"]).transform(rfm["M"])#定义RFM模型,需要特别注意的是,R值代表距离上次消费时间间隔,值越小客户价值越高,与F和M值正好相反。def get_label(r,f,m):    if (r==0)&(f==1)&(m==1):        return "高价值客户"    if (r==1)&(f==1)&(m==1):        return "重点保持客户"    if((r==0)&(f==0)&(m==1)):        return "重点发展客户"    if (r==1)&(f==0)&(m==1):        return "重点挽留客户"    if (r==0)&(f==1)&(m==0):        return "一般价值客户"    if (r==1)&(f==1)&(m==0):        return "一般保持客户"    if (r==0)&(f==0)&(m==0):        return "一般发展客户"    if (r==1)&(f==0)&(m==0):        return "潜在客户"def RFM_convert(df):    df["Label of Customer"]=df.apply(lambda x:get_label(x["R"],x["F"],x["M"]),axis=1)        df["R"]=np.where(df["R"]==0,"高","低")    df["F"]=np.where(df["F"]==1,"高","低")    df["M"]=np.where(df["M"]==1,"高","低")        return df[["R","F","M","Label of Customer"]]rfm1=RFM_convert(rfm)rfm1.head(5)
聚类分析|基于RFM模型对用户价值进行分析

PS:用户价值标签已经得到,如果想把得到的标签返回到原每个id用户上且保存导出为csv,可以用下面代码。

df = df.join(rfm1)df.to_csv("label.csv")

下面我们可以通过数据可视化直观看一下各类用户的占比情况。

value_counts=rfm1["Label of Customer"].value_counts().valueslabels=rfm1["Label of Customer"].value_counts().indexexplode=[0.1,0.1,0.1,0,0,0,0,0]color=["deepskyblue","steelblue","lightskyblue","aliceblue","skyblue","cadetblue","cornflowerblue","dodgerblue"]plt.figure(figsize=(10, 7))plt.pie(x=value_counts,labels=labels,autopct="%.2f%%",explode=explode,colors=color,wedgeprops={"linewidth":0.5,"edgecolor":"black"},textprops={"fontsize":12,"color":"black"})plt.legend(labels,bbox_to_anchor=(1, 1), loc="best", borderaxespad=0.7)plt.title("客户类别细分情况")plt.show()
聚类分析|基于RFM模型对用户价值进行分析

通过饼形图观察看出,一般发展客户数最多,占比40.72%,其次是潜在客户,高价值客户。

4.3KMeans聚类分析

上面RFM模型只用到数据集中lasthtlordergap、ordernum_oneyear、avgprice、consuming_capacity这几个直接相关变量,但这些变量并不能完全涵盖用户特征,所以,接下来用K-Means聚类的方法引入其他变量进一步探究分析,观察不同类别客户的特征。

4.3.1相关性分析

观察整个数据集可以大体分为两个类别:用户信息和酒店信息。用户信息,即主体是用户,如consuming_capacity (消费能力指数)、price_sensitive(价格敏感指数)、starprefer(星级偏好)等,这些变量主要描述的是用户信息;酒店信息,即主体是酒店,如hotelcr (当前酒店历史cr),commentnums (当前酒店点评数)、novoters (当前酒店评分人数)等,这些变量主要描述的酒店信息。

# 用户特征提取user_features=["visitnum_oneyear","starprefer","sid","price_sensitive","ordernum_oneyear","ordercanncelednum","ordercanceledprecent","lastpvgap",               "lasthtlordergap","landhalfhours","iforderpv_24h","historyvisit_totalordernum","historyvisit_avghotelnum","h",               "delta_price2","delta_price1","decisionhabit_user","customer_value_profit","ctrip_profits","cr","consume_level"]#生成用户特征的相关性矩阵user_corr=df[user_features].corr()#绘制用户特征的相关性矩阵热度图fig,ax = plt.subplots(figsize=(18, 12))sns.heatmap(user_corr, xticklabels=True, yticklabels=True, square=False, linewidths=.5, annot=True, cmap="YlGnBu")
聚类分析|基于RFM模型对用户价值进行分析

从热图中看出:

  • ordernum_oneyear和historyvisit_totalordernum的相关性高达0.93,两者都是表示用户1年内订单数,特征选取时可以只选择其一,这里选择ordernum_oneyear作为用户年订单数的特征;
  • delta_price1和delta_price2的相关性达到了0.91,前者表示用户偏好价格-24小时浏览最多酒店价格,后者表示用户偏好价格-24小时浏览酒店平均价格,一定程度上说明浏览最多的酒店价格影响着平均价格,可以理解为众数和平均数的关系,这里选择PCA提取一个主成分表示用户价格偏好;
  • decisionhabit_user和historyvisit_avghotelnum相关性达到了0.89,前者表示用户决策习惯,后者表示近3个月用户历史日均访问酒店数,说明用户的决策习惯可能是基于用户近3个月的日均访问数判定的,这里选择用PCA提取一个主成分表示用户近期的日均访问量;
  • customer_value_profit和ctrip_profits这两个特征之间相关性达到了0.85,前者表示用户近一年的价值,后者也表示用户价值,细分区别在于衡量的时间长度不同,这里也选择PCA提取一个主成分表示用户价值。

4.3.2PCA降维

PCA降维可以在尽量保证"信息量不丢失"的情况下,对原始特征进行降维,也就是尽可能将原始特征往具有最大投影信息量的维度上进行投影,将原特征投影到这些维度上,使降维后信息量损失最小。

#删除historyvisit_totalordernum列delete_columns = ["historyvisit_totalordernum"]df.drop(delete_columns,axis=1,inplace= True)#PCA主成分分析from sklearn.decomposition import PCA#定义降维函数def PCA_transform(df,col,new_col,n=1):    pca=PCA(n_components=n)    pca.fit(df[col])    df[new_col]=pca.transform(df[col])    # 添加新生成列    df.drop(col,axis=1,inplace= True)   # 删除原来的特征列#选择特征price_prefer=["delta_price1","delta_price2"]                       # 用户价格偏好visit_num=["decisionhabit_user","historyvisit_avghotelnum"]        #用户访问数c_value=["customer_value_profit","ctrip_profits"]                  # 用户价值#应用函数PCA_transform(df,price_prefer,"price_prefer")PCA_transform(df,visit_num,"visit_num")PCA_transform(df,c_value,"c_value"

4.3.3K-Means聚类

K-Means算法是一种基于划分的无监督聚类算法,它以 k 为参数,把 n 个数据对象分成 k 个簇,使簇内具有较高的相似度,而簇间的相似度较低。

# 选取刻画用户的重要指标user_feature = ["consume_level","c_value","day_advanced","h","lasthtlordergap","lastpvgap",                "landhalfhours","ordernum_oneyear","ordercanceledprecent","price_sensitive","price_prefer","sid","starprefer","visit_num"]user_attributes = df[user_feature]# 数据标准化from sklearn.preprocessing import StandardScalerscaler = StandardScaler()scaler.fit(user_attributes)user_attributes = scaler.transform(user_attributes)#K-Means聚类from sklearn.cluster import KMeansKmeans=KMeans(n_clusters=3,random_state=13)                                     # 建立KMean模型Kmeans.fit(user_attributes)                                                     # 训练模型k_char=Kmeans.cluster_centers_                                                  # 得到每个分类的质心personas=pd.DataFrame(k_char.T,index=user_feature,columns=["0类","1类","2类"])  # 用户画像表personas
聚类分析|基于RFM模型对用户价值进行分析
#绘制热力图fig,ax = plt.subplots(figsize=(5, 10))sns.heatmap(personas, xticklabels=True, yticklabels=True, square=False, linewidths=.5, annot=True, cmap="YlGnBu")
聚类分析|基于RFM模型对用户价值进行分析

从热力图中可以直观看出:

  • 1类特征比较明显,consume_level消费水平为1.6,ordernum_oneyear用户年订单数为0.91,starprefer星级偏好为1.1,多个正向字段都为最大值,我们判定1类为高价值用户;
  • 2类特征中,lasthtlordergap一年内距离上次下单时长为1.8是三类中最大的,ordernum_oneyear用户年订单数为-0.46是三类中最小,c_value用户价值为-0.33也是三类中最小的,我们判定2类为低价值用户;
  • 0类,相对1类和2类特征不明显,大都处于中间值,我们判定0类为中价值用户。
#绘制饼形图class_k=list(Kmeans.labels_)  # 每个类别的用户个数percent=[class_k.count(0)/len(user_attributes),class_k.count(1)/len(user_attributes),class_k.count(2)/len(user_attributes)]   # 每个类别用户个数占比fig, ax = plt.subplots(figsize=(11,11))colors=["green","darkblue","lightyellow"]types=["中价值用户","高价值用户","低价值用户"]ax.pie(percent,radius=1,autopct="%.2f%%",pctdistance=0.75,colors=colors,labels=types)ax.pie([1], radius=0.6,colors="w")plt.show()
聚类分析|基于RFM模型对用户价值进行分析

从饼形图中看出,高价值用户和低价值用户占比比较接近,都在15%左右;处于中间的中价值用户占比最高,占比约70%。

五、总结

基于上面聚类分析得到的用户特征,分别对不同价值用户给出运营建议:

  • 高价值用户:消费能力高,预定量和预定频率也都比较高,偏好星级酒店,但对价格比较敏感,这部分群体可能为商务人士,经常需要出差住宿但公司对差旅报销有价格限制,针对这部分用户群体,可以集中推荐交通便利、性价比高的商务酒店,同时,可以加强和企业合作,推广携程企业版,方便差旅审批报销,加强用户黏性;
  • 中价值用户分析:用户访问数和访问频率都比价高,但预定量不是很高,喜欢低价格的,说明这部分用户有一定的订房需求但比较注重价格,长时间在搜索对比价格,决策时间比较长,可以优化推荐算法,对这部分用户主要推送价格实惠的酒店,同时,系统对比其他订房平台上的房间价格,低于其他平台价格的房间可以特别标注全网最低,节省用户决策时间,提高用户体验,从而提升用户在本平台的使用率;
  • 低价值用户分析:最明显的特征就是登录访问频率低(距离上次访问间隔时间长),这部分用户可能是偶尔才在携程平台上预定酒店,重点在于激活用户,对长久未登录使用用户,可以发放优惠券,刺激消费;这部分群体也有可能住宿方面需求原本就小,目前属于潜在用户,可以定期推送平台信息,继续维持用户。

 

End.

作者:以它为镜

本文为转载分享,如果涉及作品、版权和其他问题,请联系我们第一时间删除(微信号:lovedata0520)

更多文章前往首页浏览http://www.itongji.cn/

  • 我的微信公众号
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: