5.7案例:基于RFM的精细化用户管理
案例背景:在用户2015-2018年订单数据的基础上,对用户进行分群,总结每个组用户特征,以便于精细化运营,制定定制化和差异性的营销和关怀;
分析思路:基于RFM对用户进行分群,将三个维度分别作三个区间的离散化
import time
import numpy as np
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from pyecharts.charts import Bar3D
import pyecharts.options as opts
sheet_names = ["2015","2016","2017","2018","会员等级"]
sheet_datas = [pd.read_excel(r"D:\data_analysis_and_data_operation_with_python\python_book_v2\chapter5\sales.xlsx",sheet_name=i) for i in sheet_names]
#查看各个表是否存在缺失值
#for i in sheet_datas:
# print(i.info())
for each_name,each_data in zip(sheet_names,sheet_datas):
print("[data summary for {0:=^50}]".format(each_name))
print("Overview:","\n",each_data.head())
print("DESC:","\n",each_data.describe())
print("NA records",each_data.isnull().any(axis=1).sum())
#数据均可以读取,无格式错误。缺失值总共只有一个,可以直接删除,其次订单金额分布极不均衡,根据业务背景,极大值产生是合理的(有贵重商品),其次金额小于1的订单,没有实际意义;
#处理缺失值和删除订单金额小于1的数据
for ind,each_data in enumerate(sheet_datas[:-1]):
sheet_datas[ind] = each_data.dropna()
sheet_datas[ind] = each_data[each_data["订单金额"]>1]
#便于计算,最近一购买时间间隔
sheet_datas[ind]["max_years_date"] = each_data["提交日期"].max()
#将年份数据进行纵向合并
data_merge = pd.concat(sheet_datas[:-1],axis=0)
#获取购买时间与年末的差值(最近一次购买),获取购买年份
data_merge["date_interval"] = data_merge["max_years_date"] - data_merge["提交日期"]
data_merge["year"] = data_merge["提交日期"].dt.year
#date_interval时间戳转化为数字
data_merge["date_interval"] = data_merge["date_interval"].apply(lambda x:x.days)
#提取“购买金额”,“购买次数”,“最近一次购买”时间字段,有两种方法,数据透视表以及groupby
#rfm_gb = pd.pivot_table(data_merge,index=["year","会员ID"],values=["订单号","订单金额","date_interval"],aggfunc=
# {"订单号":"count","订单金额":"sum","date_interval":"min"}).reset_index()
rfm_gb = data_merge.groupby(["year","会员ID"],as_index=False).agg({
"date_interval":"min",
"提交日期":"count",
"订单金额":"sum"})
rfm_gb.columns=["year","会员ID","r","f","m"]
#查看属性分布
rfm_gb[["r","f","m"]].describe()
r | f | m | |
count | 148591 | 148591 | 148591 |
mean | 165.524043 | 1.365002 | 1323.741329 |
std | 101.988472 | 2.626953 | 3753.906883 |
min | 0 | 1 | 1.5 |
25% | 79 | 1 | 69 |
50% | 156 | 1 | 189 |
75% | 255 | 1 | 1199 |
max | 365 | 130 | 206251.8 |
数据解读,最近一次购买时间分布较为均匀,购买频率大部分用户为一次,主要是因为行业属性(大家电)原因,用户一年购买一次较为普遍,那么最近一次购买时间分布均为也是此原因,可以认为家电购买时间随机分布;(个人感觉将最近一次购买时间作为重要指标不合适)
#临界点划分,r和m以四分位点划分即可,f则以[0,2,5,130]进行划分;
#定义区间边界,注意最小值,python进行区间分割时,是左开右闭区间
r_bins = [-1,79,255,365]
f_bins = [0,2,5,130]
m_bins = [-1,69,1199,206252]
#确定rfm因子权重,基于会员等级给予权重
rfm_merge = pd.merge(rfm_gb,sheet_datas[-1],on="会员ID",how="inner")
clf = RandomForestClassifier()
clf = clf.fit(rfm_merge[["r","f","m"]],rfm_merge["会员等级"])
weights = clf.feature_importances_
#rfm分箱,并将分类属性转化为数值属性
rfm_gb["r_score"] = pd.cut(rfm_gb["r"],r_bins,labels = [i for i in range(len(r_bins)-1,0,-1)])
rfm_gb["f_score"] = pd.cut(rfm_gb["f"],f_bins,labels = [i+1 for i in range(len(f_bins)-1)])
rfm_gb["m_score"] = pd.cut(rfm_gb["m"],m_bins,labels = [i+1 for i in range(len(m_bins)-1)])
#计算RFM加权得分
rfm_gb = rfm_gb.apply(np.int32)
rfm_gb["rfm_score"] = rfm_gb["r_score"]*weights[0] + rfm_gb["f_score"]*weights[1]+rfm_gb["m_score"]*weights[2]
#计算RFM组合分群,
rfm_gb["r_score"] = rfm_gb["r_score"].astype(np.str)
rfm_gb["f_score"] = rfm_gb["f_score"].astype(np.str)
rfm_gb["m_score"] = rfm_gb["m_score"].astype(np.str)
rfm_gb["rfm_group"] = rfm_gb["r_score"].str.cat(rfm_gb["f_score"]).str.cat(rfm_gb["m_score"])
#保存数据文件
rfm_gb.to_excel(r"D:\data_analysis_and_data_operation_with_python\sales_rfm_score.xlsx")
#RFM图形展示,只展示年份,rfm分组,用户数量
display_data = rfm_gb.group_by(["rfm_group","year"],as_index=False)["会员ID"].count()
display_data.columns = ["rfm_group","year","number"]
display_data["rfm_group"] = display_data["rfm_group"].astype(np.int32)
#画图
bar3d = Bar3D(init_opts=opts.InitOpts(width="900px", height="600px"))
range_color = ["#313695","#4575b4","#74add1","#abd9e9","#e0f3f8","#ffffbf",
"#fee090","#fdae61","#f46d43","#d73027","#a50026"]
bar3d.add(
series_name="rfm分组结果",
data = [d.tolist() for d in display_data.values]
).set_global_opts(
visualmap_opts=opts.VisualMapOpts(
max_=display_data["number"].max(),
range_color=range_color,
))
bar3d.render(r"D:\data_analysis_and_data_operation_with_python\sales_rfm_score.html")
结果分析:
用户标签 | 用户数量占比 | 用户消费金额占比 | 运营思路 |
212 | 24.79% | 5.58% | 可发展的一般性群体,通过运营手段维持并提升其消费状态 |
211 | 12.80% | 0.32% | 可发展的低价值群体,通过运营手段提升其购买金额 |
312 | 12.55% | 2.86% | 有潜力的一般性群体,购买新近度高,单忠诚度一般,通过其最近购买的商品,推荐相关商品 |
112 | 11.34% | 2.53% | 可挽回的一般性群体,通过多种方式触达客户并挽回 |
213 | 11.02% | 31.48% | 可发展的高价值群体,发展重点是提高其购物频率 |
311 | 6.24% | 0.16% | 有潜力的低价值群体,可以通过分析其渠道,加大相应渠道的投入,引导客户复购 |
111 | 6.14% | 0.16% | 各个维度都比较差的群体,主要通过多种策略挽回客户(资源足够的情况下) |
313 | 5.61% | 16.57% | 有潜力的高价值群体,发展重点是提高其购物频率 |
113 | 5.07% | 14.19% | 可挽回的高价值群体,可适当的进行人工介入 |
123 | 1.30% | 4.80% | |
333 | 0.33% | 4.53% | 绝对忠诚的高价值各户,应为其提供相应的VIP服务 |
233 | 0.70% | 9.21% | 一般性的高价值客户,重点在于提升新近购买度 |
133 | 0.32% | 4.66% | |
223 | 0.25% | 1.33% | |
322 | 0.28% | 0.09% | 有潜力的普通群体,需要提升购买频次,和额度 |
323 | 0.25% | 1.14% | |
332 | 0.02% | 0.01% |
总结:1,个人认为该案例数据不太实用RFM模型,因为数据北京是大家电行业,大型的家用电器一般属于耐用品,属于绝对的低频消费,因此在购买频次这个指标很难看出客户的价值,其次也很难通过运营提高购买频次;最近的购买时间也是如此,如果你购买的时间越短,反而不会再进行购买;是否可以根据产品的生命周期,提醒客户更新换代,并推出相应的以旧换新服务;