参考书目:《深入浅出Pandas:利用Python进行数据处理与分析》
FRM模型
FRM模型是典型的用户分层模型,评估用户的消费衡量价值贡献的工具,R是消费间隔,F是消费频率,M是消费金额。
本次利用pandas进行FRM模型构建和分析。
先导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams ['font.sans-serif'] ='SimHei' #显示中文
plt.rcParams ['axes.unicode_minus']=False #显示负号
# 构建一个数据集
import faker
f=faker.Faker('zh-cn')
df=pd.DataFrame({'用户':[f.name() for i in range(2000)],
'购买日期':[f.date_between(start_date='-1y',end_date='today') for i in range(2000)],
'金额':[f.random_int(10,100) for i in range(2000)]
})
df.head()
转化一下时间类型
df=df.astype({'购买日期':'datetime64[ns]'})
#df['购买日期']=df['购买日期'].astype('datetime64[ns]')
df.dtypes
#构建R特征, 先将用户分组,然后计算消费的最大日期,再用现在的时间减去,计算天数
r=(df.groupby('用户').apply(lambda x:(pd.Timestamp('today')-x['购买日期'].max())).dt.days)
r
#构建F特征
f=(df.groupby(['用户']).apply(lambda x:x['购买日期'].nunique()))
f.sort_values()
#构建M特征
df.groupby(['用户'])['金额'].mean()
#合并FRM
(pd.DataFrame({'r':r,'f':f})).assign(m=lambda x:df.groupby(['用户']).sum()['金额']/x.f)
#将数据分箱,标号123等级
#将数据分箱,标号123等级
data=(pd.DataFrame({'r':r,'f':f})
.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,1.5,2.5,float('inf')],labels=[1,2,3]))
.assign(m_s=lambda x:pd.cut(x.m,bins=[0,30,60,float('inf')],labels=[1,2,3],right=False)) )
data
#然后可以利用k均值聚类
data=data.iloc[:,-3:]
data.head()
数据标准化然后K均值聚类为4类
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(data)
data_s = scaler.transform(data)
from sklearn.cluster import KMeans
kmeans_model = KMeans(n_clusters=4, random_state=123, n_init=20) #聚为4类
kmeans_model.fit(data_s)
kmeans_labels = kmeans_model.labels_ # 样本的类别标签
kmeans_labels
画图可视化
data=data.astype('float')
data['label']=kmeans_labels
column = data.columns[:-1].tolist() # 列表头
fig = plt.figure(figsize=(20, 14), dpi=128) # 指定绘图对象宽度和高度
for i in range(3):
plt.subplot(2,3, i + 1) # 2行3列子图
ax = sns.violinplot(x='label',y=column[i],width=0.8,saturation=0.9,lw=0.8,palette="Set2",orient="v",inner="box",data=data)
plt.xlabel((['客户群' + str(i) for i in range(5)]),fontsize=14)
plt.ylabel(column[i], fontsize=16)
plt.tight_layout()
plt.show()
然后可以根据客户群不同的特征去进行分类制定营销策略
构建FRM特征之后,还可以直接按高于平均水平还是低于平均水平进行打分
(pd.DataFrame({'r':r,'f':f})
.assign(m=lambda x:df.groupby(['用户']).sum()['金额']/x.f)
.assign(r_e=lambda x:(x.r>x.r.mean())*1)
.assign(f_e=lambda x:(x.f>x.f.mean())*1)
.assign(m_e=lambda x:(x.m>x.m.mean())*1)
.assign(label=lambda x:x.r_e.astype('string')+x.f_e.astype('string')+x.m_e.astype('string'))
)
然后利用map映射一下
label_names={'111':'重要价值客户','110':'一般价值客户','101':'重要发展客户',
'100':'一般发展客户','011':'重要保持客户','010':'一般保留客户',
'001':'重要挽留客户','000':'一般挽留客户'}
(pd.DataFrame({'r':r,'f':f})
.assign(m=lambda x:df.groupby(['用户']).sum()['金额']/x.f)
.assign(r_e=lambda x:(x.r>x.r.mean())*1)
.assign(f_e=lambda x:(x.f>x.f.mean())*1)
.assign(m_e=lambda x:(x.m>x.m.mean())*1)
.assign(label=lambda x:x.r_e.astype('string')+x.f_e.astype('string')+x.m_e.astype('string'))
.assign(客户的等级=lambda x:x.label.map(label_names))
)
然后可以根据不同的客户标签分类制定营销策略