Python分析RFM
-- coding: utf-8 --
1. 概念:RFM分析是根据客户活跃程度和交易金额贡献,进行客户价值细分的一种方法.
R(Recency):近度,客户最近一次交易时间的间隔。R越大,表示客户越久未发生交易,R越小,表示客户越近有交易发生
F(Frequency):频度,客户在最近一段时间内交易的次数。F越大,表示客户交易越平凡,F越小,表示客户不够活跃
M(Monetary):额度,客户在最近一段时间内交易的金额。M越大,表示客户价值越高,M越小,表示客户价值越低
2. RFM分析过程
2.1 计算RFM各项分值
R_S,距离当前日期越近,得分越高,最高5分,最低1分
F_S,交易频率越高,得分越高,最高5分,最低1分
M_S,交易金额越高,得分越高,最高5分,最低1分
2.2 汇总RFM分值
RFM = 100R_S + 10F_S + 1*M_S (业务专家得出的结论,可以看出不同项的权重不一样)
2.3 根据RFM分值对客户分类
3. RFM分析前提
3.1 最近有过交易行为的客户,再次发生交易的可能性要高于最近没有交易行为的客户;
3.2 交易频率较高的客户比交易频率较低的客户,更有可能再次发生交易行为;
3.3 过去所有交易总金额较多的客户,比交易总金额较少的客户,更有消费积极性
python中没有计算RFM的包,因为我们需要手工实现
import numpy
import pandas
data = pandas.read_csv("D:/workspaces/python/pythonStudy/30.csv")
30.csv包括列:OrderID、CustomerID、DealDateTime成交日期、Sales订单金额,下载地址: [
https://pan.baidu.com/s/1vIFHvVRHXNr_gCmOpns8Tg
](https://pan.baidu.com/s/1vIFHvVRHXNr_gCmOpns8Tg)
计算最近一次消费距离今天的距离:
data['DealDateTime'] = pandas.to_datetime(
data.DealDateTime,
format='%Y/%m/%d'
)
data['DateDiff'] = pandas.to_datetime(
'today'
) - data['DealDateTime']
得到每笔交易记录距离当前日期的天数
data['DateDiff'] = data['DateDiff'].dt.days
得到每个用户的最近一笔交易距离今天的日期天数(使用用户id进行分组,然后得到订单距离当前日期的最小值)
R_Agg = data.groupby(
by=['CustomerID']
)['DateDiff'].agg({
'RecencyAgg':numpy.min
})
距离计算结束
计算每个用户的交易订单数量(使用用户id进行分组,然后得到每个分组的记录数量)
F_Agg = data.groupby(
by=['CustomerID']
)['OrderID'].agg({
'FrequencyAgg':numpy.size
})
计算每个用户的消费总额(使用用户id进行分组,然后对订单金额进行求和)
M_Agg = data.groupby(
by=['CustomerID']
)['Sales'].agg({
'MonetaryAgg':numpy.sum
})
将三个数据整合起来:
aggData = R_Agg.join(F_Agg).join(M_Agg) #得到了一个新的数据框,包含三列
对aggData的每个列都需要进行对应的排序分组,为每个组给一个得分值(1-5分)
计算R得分情况:
计算各分位值,用于确定分组界限
bins = aggData.RecencyAgg.quantile(
q = [0,0.2,0.4,0.6,0.8,1],#将0-1分位5部分
interpolation='nearest'
)
bins[0] = 0 #避免最小值不闭合的错误,将最小值设置为0
labels = [5,4,3,2,1] #定义每个区间的得分,以标签的形式实现。近度越小,得分越高
R_S = pandas.cut(
aggData.RecencyAgg,
bins,
labels = labels
)
计算F得分情况:
bins = aggData.FrequencyAgg.quantile(
q = [0,0.2,0.4,0.6,0.8,1],#将0-1分位5部分
interpolation='nearest'
)
bins[0] = 0
labels = [1,2,3,4,5] #频率越高,得分越高
F_S = pandas.cut(
aggData.FrequencyAgg,
bins,
labels = labels
)
计算M得分情况:
bins = aggData.MonetaryAgg.quantile(
q = [0,0.2,0.4,0.6,0.8,1],#将0-1分位5部分
interpolation='nearest'
)
bins[0] = 0
labels = [1,2,3,4,5] #额度越高,得分越高
M_S = pandas.cut(
aggData.MonetaryAgg,
bins,
labels = labels
)
将各得分值作为新的列赋值回去
aggData['R_S'] = R_S
aggData['F_S'] = F_S
aggData['M_S'] = M_S
根据RFM的经验公式计算RFM的值
aggData['RFM'] = 100R_S.astype(int) + 10F_S.astype(int)+1*M_S.astype(int)
将用户分为8类
计算分位值,值越大,表示用户越重要
bins = aggData.RFM.quantile(
q = [0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1],
interpolation='nearest'
)
bins[0] = 0
labels = [1,2,3,4,5,6,7,8]
aggData['level'] = pandas.cut(
aggData.RFM,
bins,
labels = labels
)
验证每种用户大概是如何分布的:
aggData = aggData.reset_index() #重置行索引(从0开始),之前的索引列变为CustomerID
aggData.sort(
['level','RFM'],
ascending=[1,1]
)
观察每个level的用户的数量:
aggData.groupby(
by = ['level']
)['CustomerID'].agg({
'size':numpy.size
})