040—pandas 实现RFM用户分层

使用步骤

读入数据

代码如下(示例):

# RFM 是典型的用户分层方法, 是评估用户消费能力、 衡量用户贡献价值的重要工具。
# RFM 代表的是最近一次消费时间间隔(Recency)、消费频率(Frequency)和消费金额(Monetary)。
# 本案例将利用 Pandas 建立用户消费 RFM 模型,实现精细化运营。
import pandas as pd
# 构造数据
import faker # 安装:pip install faker

f = faker.Faker('zh-cn')

df = pd.DataFrame({
    '用户': [f.name() for i in range(20000)],
    '购买日期': [f.date_between(start_date='-1y',
    end_date='today') for i in range(20000)],
    '金额': [f.random_int(10, 100) for i in range(20000)]
})

# 数据类型转换
df = df.astype({'购买日期': 'datetime64[ns]'})
# 数据类型
df.head()

在这里插入图片描述

# 首先来计算 R 值。R 为最后一次购买时间距今的天数,R 值越大代表用户越有可能处于沉睡状态,流失风险越大:
# r 为购买间隔天数
r = (
    df.groupby('用户')
    .apply(lambda x: (pd.Timestamp('today')-x['购买日期'].max()))
    .dt
    .days
)

r

在这里插入图片描述

# 先对用户分组,分组后取每组用户最近购买时间(时间的最大值),然后用今日减去最近购买时间,就得到了最近购买间隔天数。
# 接下来计算 F 值。F 值是消费频率,消费频次越高代表用户黏性越强。
# 我们将同一天购买多次的情况算作一次。算法也是先对用户分组,然后取购买日期的不重复数量:
# f 为购买次数,一天多次算一次
f = (
    df.groupby(['用户'])
    .apply(lambda x: x['购买日期'].nunique())
)
f.sort_values()

在这里插入图片描述

# 接下来将 RFM 数据合并。由于我们之前在计算 R 值和 F 值后都是以用户名称为索引的,因此直接用两个 Series 构造 DataFrame,同时算出 M 值:
# 合并RFM
(
    pd.DataFrame({'r': r,'f': f,})
    # m为总金额/购买次数
    .assign(m=lambda x: df.groupby(['用户'])['金额'].sum()/x.f)
)

在这里插入图片描述

# 这样,每个用户的 RFM 值就计算出来了。
# 接着给 RFM 打分,为了方便演示,采用 3 分制,将 RFM 的值分为三个等级。
# R 值使用 pd.qcut() 平均分为三段,R 越大代表间隔时间越长,对间隔近的打 3 分,次之打 2 分,最远的打 1 分。F 值和 M 值越大越好,因此我们用 pd.cut() 人工分段,分别打 1、2、3 分。代码如下:
(
    pd.DataFrame({'r': r,'f': f,})
    # m为总金额/购买次数
    .assign(m=lambda x: df.groupby(['用户'])['金额'].sum()/x.f)
    .assign(r_s=lambda x: pd.qcut(x.r, q=3, labels=[3,2,1]))
    .assign(f_s=lambda x: pd.cut(x.f,bins=[0,2,5,float('inf')], labels=[1,2,3],
    right = False))
    .assign(m_s=lambda x: pd.cut(x.m,bins=[0,30,60,float('inf')], labels=[1,2,3],
    right = False))
)

在这里插入图片描述

# 这样,就给每个用户的 RFM 完成了打分。
# 接下来进行分值归一化,我们把高于平均水平的归为 1,低于平均水平的归为 0:
(
    pd.DataFrame({'r': r,'f': f,})
    # m为总金额/购买次数
    .assign(m=lambda x: df.groupby(['用户'])['金额'].sum()/x.f)
    .assign(r_s=lambda x: pd.qcut(x.r, q=3, labels=[3,2,1]))
    .assign(f_s=lambda x: pd.cut(x.f,bins=[0,2,5,float('inf')], labels=[1,2,3], right = False))
    .assign(m_s=lambda x: pd.cut(x.m,bins=[0,30,60,float('inf')], labels=[1,2,3], right = False))
    .assign(r_e=lambda x: (x.r_s.astype(int) > x.r_s.astype(int).mean())*1)
    .assign(f_e=lambda x: (x.f_s.astype(int) > x.f_s.astype(int).mean())*1)
    .assign(m_e=lambda x: (x.m_s.astype(int) > x.m_s.astype(int).mean())*1)
)

在这里插入图片描述

# 最后将这些打分形成一个统一的标签。
# 在打分设计时我们给正向的方面打了高分,再将分值的重要度 R、F、M 分别转化为数字,放在百位、十位和个位:
(
    pd.DataFrame({'r': r,'f': f,})
    # m为总金额/购买次数
    .assign(m=lambda x: df.groupby(['用户'])['金额'].sum()/x.f)
    .assign(r_s=lambda x: pd.qcut(x.r, q=3, labels=[3,2,1]))
    .assign(f_s=lambda x: pd.cut(x.f,bins=[0,2,5,float('inf')], labels=[1,2,3], right = False))
    .assign(m_s=lambda x: pd.cut(x.m,bins=[0,30,60,float('inf')], labels=[1,2,3], right = False))
    .assign(r_e=lambda x: (x.r_s.astype(int) > x.r_s.astype(int).mean())*1)
    .assign(f_e=lambda x: (x.f_s.astype(int) > x.f_s.astype(int).mean())*1)
    .assign(m_e=lambda x: (x.m_s.astype(int) > x.m_s.astype(int).mean())*1)
    .assign(label=lambda x: x.r_e*100+x.f_e*10+x.m_e*1)
)

在这里插入图片描述

# 最后可以用 map 方法给数据打上中文标签:
label_names = {111:'重要价值用户',
               110:'一般价值用户',
               101:'重要发展用户',
               100:'一般发展用户',
               11:'重要保持用户',
               10:'一般保持用户',
               1:'重要挽留用户',
               0:'一般挽留用户'}


(
    pd.DataFrame({'r': r,'f': f,})
    # m为总金额/购买次数
    .assign(m=lambda x: df.groupby(['用户'])['金额'].sum()/x.f)
    .assign(r_s=lambda x: pd.qcut(x.r, q=3, labels=[3,2,1]))
    .assign(f_s=lambda x: pd.cut(x.f,bins=[0,2,5,float('inf')], labels=[1,2,3], right = False))
    .assign(m_s=lambda x: pd.cut(x.m,bins=[0,30,60,float('inf')], labels=[1,2,3], right = False))
    .assign(r_e=lambda x: (x.r_s.astype(int) > x.r_s.astype(int).mean())*1)
    .assign(f_e=lambda x: (x.f_s.astype(int) > x.f_s.astype(int).mean())*1)
    .assign(m_e=lambda x: (x.m_s.astype(int) > x.m_s.astype(int).mean())*1)
    .assign(label=lambda x: x.r_e*100+x.f_e*10+x.m_e*1)
    .assign(label_names=lambda x: x.label.map(label_names))
    .groupby('label').count().r.plot.bar()
)
# 显示如下图形,各个标签的用户数
# 这样,将用户按分值由高到低分为 9 类,运营人员可以根据不同的用户类型来制定不同的营销策略。

在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

qutip,一个高级的 Python 量子力学研究库!

目录 前言 安装 特性 基本功能 量子态的创建和操作 量子态的测量 示例代码 动力学模拟 高级功能 退相干和噪声模拟 控制和优化 量子信息学工具 实际应用场景 量子态演化研究 量子计算机模拟 量子纠错协议 总结 前言 大家好,今天为大家分享一个高级的 Pytho…

蓝桥杯-STL-string

目录 字符串定义 字符串初始化 字符串输入输出 字符串输出 字符串输入 字符串访问 字符串拷贝 字符串拼接 直接相加 append(const char*str,int n) 字符串比较 ​编辑字符串长度length()/size() 字符串查找find(string str) 查找子串substr(int a,int b) 字符串的…

家居网购项目(三)

文章目录 1.后台管理—添加家居1.需求分析2.程序框架图3.修改FurnDao添加方法add 4.修改FurnDaoImpl添加方法add 5.单元测试FurnDaoTest.java 6.修改FurnService添加方法add 7.修改FurnServiceImpl添加方法add 8.单元测试FurnServiceTest.java 9.修改furn_add.jsp10.修改FurnSe…

用于扩展Qt自身的插件(下)

扩展Qt自身的插件 引言必须满足项创建插件示例代码生成插件配置加载插件的环境创建使用插件的项目配置库和头文件依赖的步骤:应用程序代码运行结果总结引言 本文继上篇的扩展Qt自身的插件,接着记录Qt自身的插件,只不过本文提及的用于扩展Qt自身的插件是可以在QtCreator的设…

读《AI营销画布》客户关系维护的当代挑战(二)

前言 技术进步、用户连接与信息冗余这三股力量已经让人无法真正高质量的获取有用的信息,在对进步与高质量前面提出解决方案时,我们需要对挑战清楚的认识,所以,今天就这三个也解读一下。 1.信息泛滥与爆炸 如图还是19年的&#xf…

股票价格预测 | Python使用GAN预测股票价格

文章目录 效果一览文章概述代码设计效果一览 文章概述 生成对抗网络(GAN)是一种强大的机器学习模型,用于生成以假乱真的数据。然而,使用GAN来预测股票价格可能会面临以下挑战: 数据可用性:GAN需要大量的数据进行训练,以便生成准确的输出。对于股票价格预测,历史股票价…

基于单片机的智能居家火灾报警系统

摘要:采用STC15L2K32单片机设计了一种智能火灾报警系统,它是控制中心与多个不同功能的探测模块构成,实现了一个中心、多点辐射的火灾检测和报警功能。 关键词:智能居家,火灾报警系统,单片机,模块化设计。 0 引言 近些年电子技术、计算机技术为火灾报警系统和灭火系统在…

Python实现PDF页面的删除与添加

在处理PDF文档的过程中,我们时常会需要对PDF文档中的页面进行编辑操作的情况,如插入和删除页面。通过添加和删除PDF页面,我们可以增加内容或对不需要的内容进行删除,使文档内容更符合需求。而通过Python实现PDF文档中的插入和删除…

明明设置数字居中对齐,为什么excel的数字却不居中?

有时候在excel里,选中数据,设置对齐方式 左右居中,然而,数字却怎么都不居中,为什么呢? 1.按快捷键Ctrl1,打开单元格自定义格式对话框,看到是初始界面是在数字的会计专用,…

TDengine too many open files

too many open files 是比较常见的报错,尤其使用TDengine 3.0 集群时,大概率会遇到。这个报错很简单,但要想顺利解决,却涉及到很多知识点。 目录 知识点:fs.nr_open知识点:file-max & fs.file-nr知识点…

VSCode中 task.json 和 launch.json 的作用和参数解释以及配置教程

前言 由于 VS Code 并不是一个传统意义上的 IDE,所以初学者可能在使用过程中会有很多的疑惑,其中比较常见的一个问题就是 tasks.json和 launch.json两个文件分别有什么作用以及如何配置 tasks.json VSCode 官网提供的 tasks.json 配置教程 使用不同的…

探索HTTP协议的世界 | 从基础到高级应用,原理与实践相结合(请求篇)

从基础到高级应用,原理与实践相结合 什么是Http历代Http协议主要特点格式和URL协议内容请求行格式如下请求方法简单案例 消息报头报头域的格式HTTP消息报头类型普通报头优化方向报头(缓存)Cache-Control的选项其他相关的缓存报头 请求报头Acc…

CLIP大模型图文检索——原理解读及代码实现

一. 核心思想 通过自然语言处理获得的监督信号可用于训练迁移效果出色的视觉模型。本论文的作者团队构建了一个庞大的图像文本配对数据集,其中包含400 million个图片文本的配对。利用最大规模的ViT-large模型,他们提出了CLIP(Contrastive La…

Day38 代码随想录(1刷)动态规划

目录 343. 整数拆分 96. 不同的二叉搜索树 343. 整数拆分 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 ),并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1…

SQLite 在Android安装与定制方案(十七)

返回:SQLite—系列文章目录 上一篇:SQLite超详细的编译时选项(十六) 下一篇:SQLite Android 绑定(十八) 安装 有三种方法可以将 SQLite Android 绑定添加到应用程序: 1、通过…

迭代器模式:统一访问集合元素的优雅方式

在面向对象的软件开发中,迭代器模式是一种行为型设计模式,它提供了一种方法来顺序访问一个聚合对象中的各个元素,而又无需暴露该对象的内部表示。这种模式是集合处理特别是遍历集合的核心机制。本文将详细介绍迭代器模式的定义、实现、应用场…

《零基础入行IT:步步为营的转型攻略与实践策略》

在信息化社会,IT行业以其强劲的发展势头、广阔的就业前景和丰厚的薪酬待遇,吸引了无数希望转行或初入职场人士的目光。然而,对于毫无相关背景知识的人来说,如何成功叩开IT行业的大门,似乎是一项颇具挑战性的任务。本文…

element-ui的年份范围选择器,选择的年份需等于或小于当前年份,选择的年份范围必须在三年之内

写在前面 日期限制处理(禁用),下面我以我这边的需求为例, 选择的年份需等于或小于当前年份 选择的年份范围必须在三年之内 1.限制起始日期小于截止日期 1)根据用户选中的开始日期,置灰不可选的日期范围&…

[RK3399 Linux] 使用ubuntu 20.04.5制作rootfs

一、ubuntu base ubuntu base是用于为特定需求创建自定义映像的最小rootfs,是ubuntu可以运行的最小环境。 1.1 下载源码 下载ubuntu-base的方式有很多,可以从官方的地址:ttp://cdimage.ubuntu.com/ubuntu-base/releases。 也可以其它镜像地址下载,如清华源:https://mi…

【小技巧】机器学习中可视化高维向量的两种方法PCA和t-SNE,以及其原理介绍和代码示例(附代码)

使用情景:比如说现在我有一批numpy的多维向量,比如说都是256维度的,X.shape(n, 256), 已知它们都是经过训练能够在256dim的超球面上实现分类或聚类的,现在我想把它们可视化出来看看各个簇在超球面上的分布是怎样的? 1…