客户RFM模型分类
客户类型 | 最近一次交易距离观测窗口的天数(黏性) | 累计交易频次(忠诚度) | 累计交易成交额(消费能力) | 对应场景 |
---|---|---|---|---|
重要价值客户 | + | + | + | RFM都很大,优质客户 |
重要召回客户 | - | + | + | 成交量和成交额都很大,但是最近没有交易,需要召回 |
重要发展客户 | + | - | + | 成交额大,最近有交易,需要重点识别 |
重要挽留客户 | - | - | + | 成交额大,潜在的价值客户,需要挽留 |
潜力客户 | + | + | - | 成交量大,且最近有交易,需要挖掘 |
新客户 | + | - | - | 最近有交易,是新客户,需要推广 |
一般维持客户 | - | + | - | 成交量大,但是贡献不大,黏性也不高,一般维持 |
流失客户 | - | - | - | 已经流失的客户 |
客户的价值分析:
(1)客户群1 —— FM很高,R较低,可以看做是重要召回客户
(2)客户群2 —— RFM都偏低,属于低价值客户
(3)客户群3 —— R很高,但FM很低,属于新客户
客户价值排名:
客户群1 ——1—— 重要召回
客户群2 ——2—— 流失客户/低价值客户
客户群3 ——3—— 新客户
客户特点:
(1)重要召回客户:
成交量和成交额都很大,但是最近没有交易,需要发掘其潜力方形
促使这类客户在本公司消费和合作伙伴处消费。通过客户价值提升,加强满意度,促使成为高价值客户。
(2)流失客户/低价值客户:
客户所乘坐航班乘坐次数F里程M低以及较长时间无乘坐。
他们可能是在公司打折促销时才会乘坐本公司航班。
(3)新客户:
最近有交易,是新客户,需要推广。
增加与这类客户的互动,了解情况,采取一定手段,让客户生命进一步成长。
实现步骤
- 数据探索清洗
- RFM属性设计
- 维度打分
- 分值计算
- 客户分层
- 描述统计并可视化
# 导包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
plt.style.use('seaborn')
plt.rcParams["font.sans-serif"] = ["SimHei"] #显示中文,解决图中无法显示中文的问题
plt.rcParams["axes.unicode_minus"] = False #设置显示中文后,负号显示受影响。解决坐标轴上付好乱码问题
数据探索和清洗
df = pd.read_excel('PYTHON-RFM实战数据.xlsx')
df.head()
品牌名称 | 买家昵称 | 付款日期 | 订单状态 | 实付金额 | 邮费 | 省份 | 城市 | 购买数量 | |
---|---|---|---|---|---|---|---|---|---|
0 | wifi365 | 叫我李2 | 2019-01-01 00:17:59 | 交易成功 | 186 | 6 | 上海 | 上海市 | 1 |
1 | wifi365 | 0cyb1992 | 2019-01-01 00:59:54 | 交易成功 | 145 | 0 | 广东省 | 广州市 | 1 |
2 | wifi365 | 萝污萌莉 | 2019-01-01 07:48:48 | 交易成功 | 194 | 8 | 山东省 | 东营市 | 1 |
3 | wifi365 | atblovemyy | 2019-01-01 09:15:49 | 付款以后用户退款成功,交易自动关闭 | 84 | 0 | 江苏省 | 镇江市 | 1 |
4 | wifi365 | 小星期鱼 | 2019-01-01 09:59:33 | 付款以后用户退款成功,交易自动关闭 | 74 | 0 | 上海 | 上海市 | 1 |
# 删除退款
df = df.loc[df['订单状态']=='交易成功',:]
df.shape
(27793, 9)
print ("列数 : " ,df.shape[0])
print ("行数 : " ,df.shape[1])
print ("\n特征数量 : \n" ,df.columns.tolist())
print ("\n缺失值 : ", df.isnull().sum().values.sum())
print ("\n唯一值 : \n",df.nunique())
列数 : 27793
行数 : 9
特征数量 :
['品牌名称', '买家昵称', '付款日期', '订单状态', '实付金额', '邮费', '省份', '城市', '购买数量']
缺失值 : 1
唯一值 :
品牌名称 1
买家昵称 25420
付款日期 27283
订单状态 1
实付金额 280
邮费 6
省份 31
城市 345
购买数量 22
dtype: int64
# 删除缺失值,重复值,把ID改为字符类型
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)
df.reset_index(drop=True,inplace=True)
df.head(2)
品牌名称 | 买家昵称 | 付款日期 | 订单状态 | 实付金额 | 邮费 | 省份 | 城市 | 购买数量 | |
---|---|---|---|---|---|---|---|---|---|
0 | wifi365 | 叫我李2 | 2019-01-01 00:17:59 | 交易成功 | 186 | 6 | 上海 | 上海市 | 1 |
1 | wifi365 | 0cyb1992 | 2019-01-01 00:59:54 | 交易成功 | 145 | 0 | 广东省 | 广州市 | 1 |
RFM属性设计
# 提取三个关键字段
df1 = df[['买家昵称','付款日期','实付金额']]
df1['付款日期'] = pd.to_datetime(df1.付款日期)
C:\Users\Administrator\anaconda3\lib\site-packages\ipykernel_launcher.py:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
"""Entry point for launching an IPython kernel.
df1