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提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 79
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花 Show Python

你的打赏会让我有创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值