使用步骤
读入数据
代码如下(示例):
# 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提供了大量能使我们快速便捷地处理数据的函数和方法。