【数据分析:RFM客户价值度模型】

news2024/9/24 19:28:21

前言:
💞💞大家好,我是书生♡,本阶段和大家一起分享和探索大数据技术RFM客户价值度模型,本篇文章主要讲述了:RFM客户价值度模型等等。欢迎大家一起探索讨论!!!
💞💞代码是你的画笔,创新是你的画布,用它们绘出属于你的精彩世界,不断挑战,无限可能!

个人主页⭐: 书生♡
gitee主页🙋‍♂:闲客
专栏主页💞:大数据开发
博客领域💥:大数据开发,java编程,前端,算法,Python
写作风格💞:超前知识点,干货,思路讲解,通俗易懂
支持博主💖:关注⭐,点赞、收藏⭐、留言💬

目录

  • 1. 客户价值度模型介绍
  • 2. RFM模型基本流程
  • 3. RFM模型的划分区间的方法
  • 4. RFM计算案例
    • 4.1 案例背景
    • 4.2 案例数据
    • 4.3 数据计算
      • 4.3.1 数据查看
      • 4.3.2 数据预处理

1. 客户价值度模型介绍

  • 客户价值度用来评估用户的价值情况,是区分客户价值的重要模型和参考依据,也是衡量不同营销效果的关键指标之一。
  • 价值度模型一般基于交易行为产生,衡量的是有实体转化价值的行为。常用的价值度模型是RFM
  • RFM模型是根据客户
    • 最近一次购买时间R(Recency)
    • 购买频率F(Frequency)
    • 购买金额M(Monetary)计算得出RFM得分
    • 通过这3个维度来评估客户的订单活跃价值,常用来做客户分群或价值区分
    • RFM模型基于一个固定时间点来做模型分析,不同时间计算的的RFM结果可能不一样
RFM用户类别
重要价值用户
重要发展用户
重要保持用户
重要挽留用户
一般价值用户
一般发展用户
一般保持用户
一般挽留用户

在这里插入图片描述

2. RFM模型基本流程

  1. 设置要做计算时的截止时间节点(例如2024-08-01),用来做基于该时间的数据选取和计算。
  2. 在客户数据库中,以今天为时间界限向前推固定周期(例如1年),得到包含每个客户的客户ID、订单时间、订单金额的原始数据集。一个客户可能会产生多条订单记录。
  3. 数据预计算。从订单时间中找到各个客户距离截止时间节点最近的订单时间作为最近购买时间;以会员ID为维度统计每个用户的订单数量作为购买频率;将用户多个订单的订单金额求和得到总订单金额。由此得到R、F、M三个原始数据量。
  4. R、F、M分区。对于F和M变量来讲,值越大代表购买频率越高、订单金额越高;但对R来讲,值越小代表离截止时间节点越近,因此值越好。对R、F、M分别使用五分位法做数据分区(三分位也可以,分位数越多划分得越详细)。需要注意的是,对于R来讲需要倒过来划分,离截止时间越近的值划分越大。这样就得到每个用户的R、F、M三个变量的分位数值。
  5. 将3个值组合或相加得到总的RFM得分。对于RFM总得分的计算有两种方式,一种是直接将3个值拼接到一起,例如RFM得分为312、333、132;另一种是直接将3个值相加求得一个新的汇总值,例如RFM得分为6、9、6。
  • R就是距离自定义的时间点最近一次购买的时间间隔、间隔越小得分越高
  • F就是自定义的时间范围内购买频率、次数越多得分越高
  • M就是自定义的时间范围内购买总金额,总额越大得分越高
  • RFM的区间和其对应的得分由我们自定义

3. RFM模型的划分区间的方法

RFM(Recency, Frequency, Monetary Value)模型是一种用于衡量客户价值的方法,通过分析最近一次购买时间(Recency)、购买频率(Frequency)和消费金额(Monetary Value)来评估客户的忠诚度和价值。确定RFM划分区间的常见方法包括以下几种:

  1. 等距分箱法

    • 方法:将每个指标分成若干等距区间。
    • 优点:简单易行,便于理解和解释。
    • 缺点:可能忽略数据分布的不均匀性。
  2. 等频分箱法

    • 方法:将每个指标分成若干等频区间,使得每个区间内包含大致相同数量的记录。
    • 优点:更好地反映数据的实际分布。
    • 缺点:区间边界可能不直观。
  3. K-Means聚类

    • 方法:使用K-Means算法将客户分为不同的群组。
    • 优点:能够捕捉客户行为的复杂模式。
    • 缺点:需要确定聚类的数量,并且结果可能随初始化的不同而变化。
  4. 百分位数分箱法

    • 方法:将数据分成几个百分位数区间,如五分位数(Quintiles)或十分位数(Deciles)。
    • 优点:能够反映数据分布的不均匀性。
    • 缺点:区间边界可能不易解释。
  5. 基于业务逻辑的方法

    • 方法:根据业务经验和逻辑设定区间。
    • 优点:更符合业务实际情况。
    • 缺点:需要深入了解业务背景。
  6. 动态区间划分

    • 方法:根据数据的分布动态调整区间边界。
    • 优点:适应性强,能够随着数据的变化自动调整。
    • 缺点:实现起来较为复杂。

划分区间

  • 根据所选方法划分区间,例如:
    • 等距分箱法:将R、F、M指标按等距离分成5个或10个区间。
    • 等频分箱法:将每个指标分成包含相同数量记录的区间。
    • 百分位数分箱法:将数据分成五分位数或十分位数。

示例

假设我们选择了等距分箱法,并将每个指标分为5个等级:

  • Recency ®:最近一次购买距离今天的时间(天数)。

    • R1: 最近10天内购买的客户。
    • R2: 11~20天内购买的客户。
    • R3: 21~30天内购买的客户。
    • R4: 31~40天内购买的客户。
    • R5: 超过40天前购买的客户。
  • Frequency (F):购买次数。

    • F1: 1~5次购买。
    • F2: 6~10次购买。
    • F3: 11~15次购买。
    • F4: 16~20次购买。
    • F5: 超过20次购买。
  • Monetary Value (M):总消费金额。

    • M1: 1~100元。
    • M2: 101~200元。
    • M3: 201~300元。
    • M4: 301~400元。
    • M5: 超过400元。

应用案例

假设某个客户在最近10天内购买了10次,总消费金额为500元,则该客户的RFM得分为:

  • R: R1 (最近10天内购买)
  • F: F5 (超过20次购买)
  • M: M5 (超过400元)

4. RFM计算案例

4.1 案例背景

  • 用户价值细分是了解用户价值度的重要途径,针对交易数据分析的常用模型是RFM模型
  • 业务对RFM的结果要求
    • 对用户做分组
    • 将每个组的用户特征概括和总结出来,便于后续精细化运营不同的客户群体,且根据不同群体做定制化或差异性的营销和关怀
  • 规划目标将RFM的3个维度分别做3个区间的离散化
    • 用户群体最大有3×3×3=27个
    • 划分区间过多则不利于用户群体的拆分
    • 区间过少则可能导致每个特征上的用户区分不显著
  • 交付结果
    • 给业务部门做运营的分析结果要导出为Excel文件,用于做后续分析和二次加工使用
    • RFM的结果还会供其他模型的建模使用,RFM本身的结果可以作为新的局部性特征,因此数据的输出需要有本地文件和写数据库两种方式
  • 数据说明
    • 案例的数据集为“销售表”
    • 选择近4年订单数据,从不同的年份对比不同时间下各个分组的绝对值变化情况,方便了解会员的波动
    • 程序输出RFM得分数据写入本地文件sales_rfm_score.xlsx和MySQL数据库sales_rfm_score表中

4.2 案例数据

在这里插入图片描述

  • 案例数据是某企业从2015年到2018年共4年的用户订单抽样数据,数据来源于销售系统
  • 数据在Excel中包含5个sheet,前4个sheet以年份为单位存储为单个sheet中,最后一张会员等级表为用户的等级表
  • 前4张表的数据概要如下。
    • 特征变量数:4
  • 数据记录数:30774/41278/50839/81349
    • 是否有NA值:有
  • 是否有异常值:有
  • 具体数据特征如下(前4张表的数据字段说明):
    • 会员ID:每个会员的ID唯一,由纯数字组成,整型
    • 提交日期:订单日提交日期
    • 订单号:订单ID,每个订单的ID唯一,由纯数字组成,整型
    • 订单金额:订单金额,浮点型数据
  • 会员等级表中是所有会员的会员ID对应会员等级的情况,包括以下两个字段
    • 会员ID:该ID可与前面的订单表中的会员ID关联
    • 会员等级:会员等级以数字区分,数字越大,级别越高

4.3 数据计算

4.3.1 数据查看

  • 加载数据

因为数据是存储在一个Excel中的不同页,因此要指定读取哪些页的数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
import warnings
sheet_names = ['2015','2016','2017','2018','会员等级']
list_data = []
for i in sheet_names:
    data= pd.read_excel('../data/sales.xlsx', sheet_name=i)
    list_data.append(data)
    
list_data
# sheet_datas -> [df1, df2, df3, df4, df5]
# 前4个df是每年订单数据的df, 第5个是会员等级的df

在这里插入图片描述

  • 我们在加载好数据之后,一定要先查看数据的缺失情况,查看那个列中有多少缺失值
    查看缺失值
# 查看缺失值
list_data[0].isnull().any()

在这里插入图片描述

# 查看缺失值
list_data[0].isnull().any(axis=1).sum()

在这里插入图片描述
查看数据基本情况

# 统计包含缺失值的行数
# any(axis=1): 判断每行是否包含缺失值
list_data[1].isnull().any(axis=1).sum()
for each_name, each_data in zip(sheet_names, list_data):    
    print('[data summary for ============={}===============]'.format(each_name))
    print('Overview:','\n',each_data.head(4))# 展示数据前4条
    print('DESC:','\n',each_data.describe())# 数据描述性信息
    # any(axis=1):每行是否有缺失值, 返回True或False
    print('NA records',each_data.isnull().any(axis=1).sum()) # 包含缺失值条目数    
    print('Dtypes',each_data.dtypes) # 数据类型

在这里插入图片描述
结果说明

  • 每个sheet中的数据都能正常读取,无任何错误
  • 日期列(提交日期)已经被自动识别为日期格式,后期不必转换
  • 订单金额的分布是不均匀的,里面有明显的极值
    • 例如2016年的数据中,最大值为174900,最小值仅为0.1
    • 极大极小值相差过大,数据会受极值影响
  • 订单金额中的最小值包括0、0.1这样的金额,可能为非正常订单,与业务方沟通后确认
    • 最大值的订单金额有效,通常是客户一次性购买多个大型商品
    • 而订单金额为0.1元这类使用优惠券支付的订单,没有实际意义
    • 除此0、0.1这样的金额之外,所有低于1元的订单均有这个问题,因此需要在后续处理中去掉
  • 有的表中存在缺失值记录,但数量不多,选择丢弃或填充均可

4.3.2 数据预处理

  • 汇总四年的数据
# 汇总四年的数据
data = pd.concat(list_data[:4])
data.info()

在这里插入图片描述

  • 删除包含缺失值的行数据
# 删除包含缺失值的行数据
data.dropna(inplace=True)
data.info()

在这里插入图片描述

  • 保留订单金额大于1的行数据
# 保留订单金额大于1的行数据
data = data[data['订单金额']>1]
data.info()

在这里插入图片描述

  • 添加新的一列 列名 为 年
# 提取提交日期的年份保存到year新列中
data['year'] = data['提交日期'].dt.year
data

在这里插入图片描述

  • 新增一列为 ,订单的最大日期,也就是最后一次购买的时间
# 对year新列分组, 提取每组中提交日期列的最大值, 保存到max_year_date新列中
# max_year_date: 4年订单数据集中的节点日期(当前时间)
data['max_data_year'] = data.groupby(data['year'])['提交日期'].transform('max')
data

在这里插入图片描述

  • 添加间隔日期列 (当前时间与 每个用户最后一次购买时间)
# 添加间隔日期列
data['diff_days'] = (data['max_data_year'] -data['提交日期'])
data['diff_days'] = data['diff_days'].dt.days
data

在这里插入图片描述

  • 计算RFM的原始值
# 统计每年每个用户的R/F/M原始值 -> 对年份和用户分组, 对相关列进行聚合操作
# R: 最近一次订单与当前时间的间隔天数 min()
# F: 订单数量 count()
# M: 订单总金额 sum()
#%%
rfm_data = data.groupby(by=['year','会员ID'],as_index=False).agg({'diff_days':'min','提交日期':'count','订单金额':'sum'})
rfm_data

在这里插入图片描述

  • 修改列的名称
rfm_data.columns = ['year','会员ID','R','F','M']
rfm_data

在这里插入图片描述

  • 区间划分
    首先查看RFM的每一个值的最小值,中位值,最大值等等
# 使用分位数套路进行划分
rfm_data[['R','F','M']].describe().T

在这里插入图片描述
根据业务和数据的区间范围,划分区间

# (最小值, 1/4分位值] (1/4分位值,3/4分位值] (3/4分位值, 最大值]
# r区间划分
r_bins = [-1, 79, 255, 365]
# m区间划分
m_bins = [1,69,1199,206251]
# f区间划分: 业务是大家电消费, 一年购买一次, 需要和业务沟通
f_bins = [0, 2, 5, 130]
rfm_data['R_level'] = pd.cut(rfm_data['R'], bins=r_bins, labels=['3','2','1'])
rfm_data['F_level'] = pd.cut(rfm_data['F'], bins=f_bins, labels=['1','2','3'])
rfm_data['M_level'] = pd.cut(rfm_data['M'], bins=m_bins, labels=['1','2','3'])
rfm_data

在这里插入图片描述

  • RFM组合-用户分群
    将我们每一个值合并在一起,在和规则进行判断,判断属于哪个价值的用户
# 字符串拼接操作
# 分类类型转换成字符串类型
rfm_data['R_level'] = rfm_data['R_level'].astype(np.str)
rfm_data['F_level'] = rfm_data['F_level'].astype(np.str)
rfm_data['M_level'] = rfm_data['M_level'].astype(np.str)
rfm_data['rfm_group'] = rfm_data['R_level'] + rfm_data['F_level'] + rfm_data['M_level']
rfm_data.head()

在这里插入图片描述

  • 绘制3D柱状图
display_data  =  rfm_data.groupby(by=['rfm_group','year'],as_index=False)['会员ID'].count()
display_data.columns = ['rfm_group','year','number']
display_data

在这里插入图片描述

# 导入绘制3D柱状图的库
from pyecharts.charts import Bar3D
from pyecharts import options as opts
# 以下绘制3D柱状图代码不需要写出来,能看懂就可以
# 颜色池
range_color = ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf',
               '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
# 获取数量的最大值
range_max = int(display_data['number'].max())
c = (
    Bar3D()#设置了一个3D柱形图对象
    .add(
        "不同年份不同价值会员的数量",#图例
        [d.tolist() for d in display_data.values],#数据
        xaxis3d_opts=opts.Axis3DOpts(type_="category", name='分组名称'),#x轴数据类型,名称,rfm_group
        yaxis3d_opts=opts.Axis3DOpts(type_="category", name='年份'),#y轴数据类型,名称,year
        zaxis3d_opts=opts.Axis3DOpts(type_="value", name='会员数量'),#z轴数据类型,名称,number
    )
    .set_global_opts( # 全局设置
        visualmap_opts=opts.VisualMapOpts(max_=range_max, range_color=range_color), #设置颜色,及不同取值对应的颜色
        title_opts=opts.TitleOpts(title="RFM分组结果"),#设置标题
    )
    .render('./不同价值会员的柱状图.html')
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2070933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据-99 Spark 集群 Spark Streaming DStream 文件数据流、Socket、RDD队列流

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

GATK ReadsPathDataSource类介绍

GATK(Genome Analysis Toolkit)是一个广泛使用的基因组分析工具包,它的核心库之一是htsjdk,用于处理高通量测序数据。在GATK中,ReadsPathDataSource类是负责管理和提供读取高通量测序数据文件(如BAM、SAM、CRAM)的类。 常见使用场景 数据加载:在GATK的基因组分析工具链…

MySQL的MRR(Multi-Range Read)优化原理详解

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

LeetCode:反转区间内的链表

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 反转区间内的链表题目链接方法一&#xff1a;拆开反转…

【TB作品】PIC16F1719单片机,EEPROM,PFM,读写

对于PIC16F1719单片机&#xff0c;没有直接的EEPROM&#xff0c;而是使用高耐久度的程序闪存&#xff08;PFM&#xff09;作为非易失性数据存储区域。这个区域特别适合存储那些需要频繁更新的数据。读写这个内存区域需要操作一些特殊功能寄存器&#xff0c;比如用于地址的PMADR…

2.K8s集群搭建

K8s搭建 搭建方案kubeadm搭建系统初始化操作k8s Master节点初始化将node节点加入集群安装网络插件Calico集群测试 搭建方案 minikube&#xff1a;轻量化的Kubernetes集群&#xff0c;为了能够更好学习和体验k8s功能而推出的&#xff0c;借助个人PC的虚拟化环境就可以实现Kuber…

如何使用ssm实现基于java web的网上书城系统的设计与实现+vue

TOC ssm123基于java web的网上书城系统的设计与实现vue JAVA简介 Java主要采用CORBA技术和安全模型&#xff0c;可以在互联网应用的数据保护。它还提供了对EJB&#xff08;Enterprise JavaBeans&#xff09;的全面支持&#xff0c;java servlet API&#xff0c;JSP&#xff…

【Redis】Redis客户端——Jedis(Java)

Redis Java使用案例 环境配置引入依赖配置端⼝转发连接 Redis Server Java基础代码操作Redisset 和 getexsits 和 del 环境配置 引入依赖 Java 操作 redis 的客⼾端有很多. 其中最知名的是 jedis. 创建 maven 项⽬, 把 jedis 的依赖拷⻉到 pom.xml 中. <!-- https://mvnr…

ssrf--web-ssrfme例题

将web-ssrfme.zip解压缩在Ubuntu下 Docker-compose up -d 更新后的镜像重新启动容器 可以看到已经拉取成功ssrfme镜像 我们使用端口访问文件&#xff0c;可以看到有一个过滤条件&#xff0c;它限制了file&#xff0c;dict协议&#xff0c;127.0.0.1和localhost 也不能用&…

【55-90】结构型模式

目录 一.结构型模式概述 二.代理模式 2.1 概述 2.2 结构 2.3 静态代理 2.4 JDK动态代理 2.5 CGLIB动态代理 2.6 三种代理的对比 2.7 优缺点 三.适配器模式 3.1 概述 3.2 结构 3.3 类适配器模式 3.4 对象适配器模式 3.5 应用场景 四.装饰者模式 4.1 概述 4.2 结…

从并发20到并发120之laravel性能优化

调优成果 遇到问题 单台服务并发20&#xff0c;平均响应时间1124ms&#xff0c;通过htop观察&#xff0c;发现cpu占用率达到100%&#xff08;包括sleep的进程&#xff09;&#xff0c;内存几乎没怎么用。 调优后 单机最大吞吐量达到120 响应时长不超过1000ms 硬件信息 …

数学建模----线性回归分析(引入热力图的绘制方法)

目录 0.直击重点 1.一元线性回归分析 1.1散点图的绘制 1.2相关性的分类 1.3计算相关系数 1.4模型的检验 1.5模型的预测 2.多重线性回归分析&#xff08;上&#xff09; 2.1多重线性的概念 2.2散点图的分类 2.3热力图的绘制 2.4根据结果确定新的变量 3.多重线性…

【开端】 如何判断手机号码属于哪个国家(手机号判断正则)汇总

import org.apache.commons.lang3.StringUtils; /** * 手机号判断正则 */ public enum MobileRegularExp { /** * 国家 正则 */ CN("中国", 86, "^(\\?0?86\\-?)?1[3456789]\\d{9}$"), TW("中国台湾", 886, "…

第七节 循环结构;goto语句

目录 7.1 while循环 7.1.1 if 和 while的对⽐ 7.1.2 while的执行流程 7.1.3 while的练习 7.2 for循环 7.2.1 语法形式 7.2.2 for循环的执⾏流程 7.2.3 for 循环的练习 7.3 while 和 for 循环的对比 7.4 do while 循环 7.4.1 do while 的语法形式 7.4.2 do while循…

Jamba前生今世:1.5开源来袭

AI21服务于企业&#xff0c;为企业构建基础模型和AI系统以加速GenAI在生产中的使用。AI21 成立于2017年&#xff0c;已从NVIDIA、Intel、Google等公司共筹集了3.36亿美元。它是最早将生成式AI推向大众的公司之一&#xff0c;借助AI21平台&#xff0c;企业可以构建自己的生成式A…

菲菲更名宝贝:批量处理,文件命名不再繁琐

你是否有这样的经历&#xff1f;曾几何时&#xff0c;在堆积如山的文件中迷失方向&#xff0c;为了一个个手动重命名文件而加班到深夜&#xff1f;是否渴望有一种魔法&#xff0c;能瞬间让你的文件整理得井井有条&#xff0c;让繁琐的命名工作变得轻松愉快&#xff1f;那么&…

大数据毕业设计开题报告100例

文章目录 &#x1f6a9; 1 前言1.1 选题注意事项1.1.1 难度怎么把控&#xff1f;1.1.2 题目名称怎么取&#xff1f; 1.2 开题选题推荐1.2.1 起因1.2.2 核心- 如何避坑(重中之重)1.2.3 怎么办呢&#xff1f; &#x1f6a9;2 选题概览&#x1f6a9; 3 项目概览题目1 : 深度学习社…

前端网站优化-Brotli 压缩

杨绛先生说:“岁不声不响&#xff0c;你且不慌不忙。在凡俗的烟火里&#xff0c;愿以素心&#xff0c;阅来日方长。生活总是一地鸡毛&#xff0c;繁杂琐碎的日常&#xff0c;无力掌控的局面&#xff0c;以及猝不及防的变化&#xff0c;让日子多了几分慌张”。 市井长巷&#xf…

ssrf漏洞复现

环境搭建 zhuifengshaonianhanlu/pikachu: 一个好玩的Web安全-漏洞测试平台 (github.com) 直接将其复制到linux环境下拉取docker就行 我这里已经拉去过了&#xff0c;如果拉去速度慢话&#xff0c;可以在/etc/docker下的daemon.json中配置镜像加速 vim /etc/docker/daemon.js…

大模型学习笔记 - LLM 对齐优化算法 DPO

LLM - DPO LLM - DPO DPO 概述DPO 目标函数推导DPO 目标函数梯度的推导 DPO 概述 大模型预训练是从大量语料中进行无监督学习&#xff0c;语料库内容混杂&#xff0c;训练的目标是语言模型损失&#xff0c;任务是next token prediction&#xff0c;生成的token 不可控&…