最近事情不多,琢磨着做点脚本玩玩,因为我是做会员的,就想着把会员常用的RFM模型做出来。首先准备数据,我让同事导了近半年的会员积分消费表格。
拿到表格后先处理了一下需要的信息,RFM逻辑其实就是在一定时间内根据会员的消费总额,最近一次消费日期和消费频次进行聚类,为了简单一些,我先提取自己需要的列,然后改一下字段名。
改完有用的字段是:'会员ID', '时间', '订单状态', '累加或扣减', '订单金额', '积分额', '备注'
拿来分析了一下数据,发现很多拆分的订单(我们系统记录的是分订单,一个消费可能分成好多个订单),所以需要按照日期,一天内的订单只计一个订单(这是数据的问题,如果是正常的订单不需要这一步)。
然后是对数据进行清洗,因为我这是生产系统的数据,没有空值,略过这一步,我只做了对时间格式的处理和对无效订单的处理。
然后是对表格进行透视,提取会员-订单量,会员—最近消费日期,会员-消费金额
最后就是对这几个表的数据进行排序,打标签,我每个表格打了9个标签,按照优先级从9打到1的,打完标签将表格合并起来,最后根据标签值提取需要的数据,完成。
以下是代码:
import numpy as np
import pandas as pd
# 读取文件,所有文件为字符串
df = pd.read_csv('RFMdoc//test.csv', encoding='gbk', dtype=str)
# 提取有效列
df = df[['会员ID', '时间', '订单状态', '累加或扣减', '订单金额', '积分额', '备注']]
# 更改时间列为年月日
df1 = pd.to_datetime((df['时间'])).dt.strftime('%Y-%m-%d ')
# 删除DF的时间列
del df['时间']
# 将处理过的时间列拼接回去df
df2 = pd.concat([df, df1], axis=1)
# 剪除订单状态为非已处理的订单
df3 = df2[df2.订单状态 == '已处理']
# 将积分列字符串变更为数值
df3['积分额'] = df3['积分额'].astype('float')
# 第一步将会员id和时间进行透视,每天的所有订单作为一个订单
df5 = pd.pivot_table(df3, index=['会员ID', '时间'], values='积分额', aggfunc=np.sum)
# print(df5)
# df.to_excel('rusult时间.xlsx')
# 第二步骤是,提取会员9个月内的订单数量,得到会员-订单数量 表格
df6 = pd.pivot_table(df5, index='会员ID', values='积分额', aggfunc={'积分额': 'count'})
# 对会员订单量表格进行排序
# 对表格进行排序,输出排序后的表格
def sort_df(dfx, number, name, col_name):
# 获取行数
col_df6 = dfx.shape[0]
# print(col_df6)
# 生成df_paixu
list = []
y = 0
for i in range(1, 10):
for x in range(y, i * col_df6 // number):
list.append(i)
y += 1
# 将list转化为df数据
# dfx_list = pd.DataFrame(list)
# 对dfx进行排序,按照列名排序
dfx_sorted = dfx.sort_values(col_name)
# 对排序后的列打标签
dfx_sorted[name] = list
return dfx_sorted
# print(df6)
# 第三部是提取会员距离最近的订单时间,计算距离3月7日有多少天,并排序
# 按照时间对原表排序
df7 = df3.sort_values('时间')
# 按照会员id删除重复项,保留距离最近的行
df7 = df7.drop_duplicates('会员ID', keep='last')
# 第四部是会员消费的金额
df8 = pd.pivot_table(df3, index='会员ID', values='积分额', aggfunc=np.sum)
# 以上每个维度截取九个level,然后合并表格,得到会员,9个月订单,距离今天时间,消费总额 的结果表格
df_number = sort_df(df6, number=9, name='数量排序', col_name='积分额')
df_time = sort_df(df7, number=9, name='时间排序', col_name='时间')
df_amount = sort_df(df8, number=9, name='金额排序', col_name='积分额')
df9 = pd.merge(df_number, df_time, on=['会员ID'])
df9 = pd.merge(df9, df_amount, on=['会员ID'])
# 提取df9的排序列
df9 = df9[['会员ID', '数量排序', '时间排序', '金额排序']]
# 首先将999提取出来,然后提取大于8的,然后是大于6的,然后是大于3的,最后是小于等于3的。
# 输入三个数值,提取大于这几个数值的所有数据
def get_excel(df, number_no, time_no, amount_no):
dfx = df[df['数量排序'] >= number_no]
dfx = dfx[dfx['时间排序'] >= time_no]
dfx = dfx[dfx['金额排序'] >= amount_no]
return(fdx)
get_excel(df9, 9, 9, 9)