【数据分析案例】游戏付费用户RFM分析案例

news/2025/2/12 8:16:55/

前言:

该案例由随机生成数据模拟半年时间内,对游戏用户充值金额情况进行用户价值分层


数据特征:

所有数据均为随机生成数据,一共有三个数据特征,分别是

r_datatime:充值时间,时间截格式,由radar库生成,时间范围为:2022-6-1至2022-12-30

r_uid:用户ID,字符串格式,由numpy库生成,以9开头生成1000个用户ID

r_price:充值金额,数值格式,由numpy库生成,随机抽取[10,60,180,300,680,1180,1980,3480,6480]中的一个充值面额


实践思路:

1.导入相关模块,生成随机数据

2.设置数据格式和调整显示方式

3.搭建RFM用户价值分层模式

4.按等距分箱的形式给用户打分

5.统计各层用户数量情况


案例详解:

导入相关模块,如果没有,则手动安装,安装方式: pip install 库名

import pandas as pd    # pip install pandas
import radar           # pip install radar
import numpy as np     # pip install numpy

生成随机时间

时间选取了2022年下半年,可自行调整时间节点

r_datatime = []
for d in range(10000):d = str(radar.random_datetime("2022-6-1", "2022-12-30"))r_datatime.append(d)

生成随机金额

充值面额参考了王者荣耀的充值面额,可自行调整面额数值

# 生成随机金额
r_price = []
for p in range(10000):p = np.random.choice([10, 60, 180, 300, 680, 1180, 1980, 3480, 6480])r_price.append(p)

生成1000个用户(以9开头)

数据总行数为10000条,可根据需求自行调整用户个数

r_uid = []
for u in range(10000):u = str(np.random.randint(999999000, 1000000000))r_uid.append(u)

合并数据

注:每行数据均表示为2022-6-1至2022-12-30期间,1000个用户中的一个用户充值了随机面额

data = pd.DataFrame(data={"uid": r_uid, "price": r_price, "date": r_datatime})

设置数据格式和调整显示方式

pd.set_option('expand_frame_repr', False)  # 当列太多时显示不清楚
pd.set_option('display.unicode.east_asian_width', True)  # 设置输出右对齐
data['date'] = data['date'].astype('datetime64[ns]')
data['date'] = pd.to_datetime(data['date']).dt.floor('d')  # 调整时间格式,只保留日期

注意:生成用户ID时,已设置调整为字符串格式,而randint是随机生成指定范围内的整数,只有时间需要另外调整格式

搭建RFM用户价值分层模式

RFM = data.groupby('uid', as_index=False).agg(last_date=('date', 'max'),F=('date', 'count'),M=('price', 'sum'))
RFM['R'] = (pd.to_datetime('2022-12-31') - RFM['last_date']).dt.days
RFM.drop(columns=['uid', 'last_date'], inplace=True)

按等距分箱的形式给用户打分

以下面参数为例,因为10000条数据中有1000个用户的付费情况,因此单个用户的最后付费时间R有可能拉的很长。通过统计总数据的充值均数,平均用户充值额度为1600左右,因此把F区间设置在25以下,50为假设区间(报错就往上调整)M值参考了王者荣耀的贵族阶级分层,略微调整了下,各位可自行根据数据分布设置合理区间(主要是懒得去琢磨了)。

RFM['R_score'] = pd.cut(RFM['R'],right=False,bins=[1, 7,14,30,90,200],labels=[5, 4, 3, 2, 1]).astype('int')
RFM['F_score'] = pd.cut(RFM['F'],right=False,bins=[0,4,8,10,12,50],labels=range(1, 6)).astype('int')
RFM['M_score'] = pd.cut(RFM['M'],right=False,bins=[1,500,2000,10000,40000,100000],labels=range(1, 6)).astype('int')

注意:

bins为划分范围,受用户数量、时间范围以及充值面额的影响,

因此,在调整过程中,注意适当调整bins的划分区间

用户分数统计后,根据用户评分情况设立标签

# 按平均值划分高低
RFM['R_level'] = (RFM['R_score'] >= RFM['R_score'].mean()) * 1
RFM['F_level'] = (RFM['F_score'] >= RFM['F_score'].mean()) * 1
RFM['M_level'] = (RFM['M_score'] >= RFM['M_score'].mean()) * 1
RFM['用户类别'] = RFM['R_level'].astype('str').str.cat([RFM['F_level'].astype('str'), RFM['M_level'].astype('str')])
RFM['用户类别'] = RFM['用户类别'].replace(['111', '110', '101', '100', '011', '010', '001', '000'],['重要价值客户', '一般价值客户', '重要发展客户', '一般发展客户', '重要保持客户', '一般保持客户', '重要挽留客户', '一般挽留客户'])

注:标签的评分定义可自行调整,作者是直接按平均数来划分

统计各层用户数量情况

最后,统计每个层次的用户数量,根据分布情况分析用户近半年的付费意愿

data = RFM.groupby('用户类别').agg(num=('F', 'count')).sort_values(by='num', ascending=False).reset_index()

完整代码:

# !/usr/bin/python3.7
# -*- coding:utf-8 -*-
# @author:inganxu
# CSDN:inganxu.blog.csdn.net
# @Date:2022年10月25日import pandas as pd
import radar
import numpy as np# 生成随机时间
r_datatime = []
for d in range(10000):d = str(radar.random_datetime("2022-6-1", "2022-12-30"))r_datatime.append(d)# 生成随机金额
r_price = []
for p in range(10000):p = np.random.choice([10, 60, 180, 300, 680, 1180, 1980, 3480, 6480])r_price.append(p)# 生成1000个用户
r_uid = []
for u in range(10000):u = str(np.random.randint(999999000, 1000000000))r_uid.append(u)data = pd.DataFrame(data={"uid": r_uid, "price": r_price, "date": r_datatime})
# 调整格式
pd.set_option('expand_frame_repr', False)  # 当列太多时显示不清楚
pd.set_option('display.unicode.east_asian_width', True)  # 设置输出右对齐
data['date'] = data['date'].astype('datetime64[ns]')
data['date'] = pd.to_datetime(data['date']).dt.floor('d')  # 调整时间格式,只保留日期# RFM用户价值分层模型
RFM = data.groupby('uid', as_index=False).agg(last_date=('date', 'max'),F=('date', 'count'),M=('price', 'sum'))
RFM['R'] = (pd.to_datetime('2022-12-31') - RFM['last_date']).dt.days
RFM.drop(columns=['uid', 'last_date'], inplace=True)
print(RFM)
print('\n')
print('-' * 100)
print('\n')# 按等距分箱的形式计分
RFM['R_score'] = pd.cut(RFM['R'],right=False,bins=[1, 7,14,30,90,200],labels=[5, 4, 3, 2, 1]).astype('int')
RFM['F_score'] = pd.cut(RFM['F'],right=False,bins=[0,4,8,10,12,50],labels=range(1, 6)).astype('int')
RFM['M_score'] = pd.cut(RFM['M'],right=False,bins=[1,500,2000,10000,40000,100000],labels=range(1, 6)).astype('int')
# 按平均值划分高低
RFM['R_level'] = (RFM['R_score'] >= RFM['R_score'].mean()) * 1
RFM['F_level'] = (RFM['F_score'] >= RFM['F_score'].mean()) * 1
RFM['M_level'] = (RFM['M_score'] >= RFM['M_score'].mean()) * 1
RFM['用户类别'] = RFM['R_level'].astype('str').str.cat([RFM['F_level'].astype('str'), RFM['M_level'].astype('str')])
RFM['用户类别'] = RFM['用户类别'].replace(['111', '110', '101', '100', '011', '010', '001', '000'],['重要价值客户', '一般价值客户', '重要发展客户', '一般发展客户', '重要保持客户', '一般保持客户', '重要挽留客户', '一般挽留客户'])
print(RFM)
print('\n')
print('-' * 100)
print('\n')
# 统计各类别数量
data = RFM.groupby('用户类别').agg(num=('F', 'count')).sort_values(by='num', ascending=False).reset_index()
print(data)

结语:

该案例主要是为搭建RFM用户价值模型提供代码思路

数据分析方法-RFM用户价值分层模型_inganxu的博客-CSDN博客_rfm分类法优缺点


http://www.ppmy.cn/news/736441.html

相关文章

17. Redis sentinel机制-实现高可用

Redis 的Sentinel机制是Redis官方提供的保证Redis高可用的工具,Redis Sentinel 采用Raft 分布式一致性算法来保证Redis 的高可用. 1. Sentinel 机制 1.1 Sentinel 主要功能 Monitoring(监控): Sentinel 会不断监测主服务器和从服务器是否正常运行Notification(通…

提前做好网络安全分析,运维真轻松(二)

背景 某汽车总部已部署NetInside流量分析系统,使用流量分析系统提供实时和历史原始流量。汽车配件电子图册系统是某汽车集团的重要业务系统。本次分析重点针对汽车配件电子图册系统进行预见性分析,以供安全取证、性能分析、网络质量监测以及深层网络分析…

springBoot整合redis启动报错:event executor terminated

springBoot整合redis启动报错:java.util.concurrent.RejectedExecutionException: event executor terminated 背景 redis一主两从三哨兵部署模式搭建完成后,需要整合springCloud项目,替换掉之前的redis单机模式,更改nacos配置中…

今天打开个税APP,我直接人麻了!

点击上方“码农突围”,马上关注 这里是码农充电第一站,回复“666”,获取一份专属大礼包 真爱,请设置“星标”或点个“在看 这是【码农突围】的第 432 篇原创分享 作者 l 突围的鱼 来源 l 码农突围(ID:smart…

05. Redis 环境搭建-高可用集群(HA)

在生产环境中,Redis 架构使用最多的就是Sentinel主从架构, 因为单点容易产生故障, 分片集群又过于复杂. 笔者尝试在一台服务器上搭建一个一主两从, 三个哨兵监听的Redis 集群架构。由于哨兵也可能发生单点故障,所以笔者也使用了三…

Elasticsearch(六)--ES文档的操作(中)---修改文档

一、前言 上篇文章我们了解了ES的插入和批量插入文档的操作,分别通过ES的kibana客户端以及Java高级Rest客户端进行学习,那么本篇则进入到对文档的修改操作,同新增文档,也有更新单条文档和批量更新文档操作,但还多出一…

【Redis高可用】

有时候单机形式下的redis性能不足时可能会挂掉导致系统服务异常,为了解决这个问题就有了下面这个内容。

全志H616芯片 以太网模块初始化失败如何解决?

1.【问题现象】 执行ifconfig -a/ifconfig eth0/ifconfig eth0 up命令,找不到eth0设备,有如下类似打印: rootTinaLinux:/# ifconfig -a lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0inet6 addr: ::1/128 Sco…