pandas 实现rfm模型
import pandas as pd
import numpy as np df = pd.read_csv('./zue_164466.csv') df['ptdate'] = pd.to_datetime(df['ptdate'],format='%Y-%m-%d')
df['dateDiff'] = pd.to_datetime('today')-df['ptdate']
df['dateDiff'] = df['dateDiff'].dt.days R_Agg = df.groupby(by=['user_email','product_name'])['dateDiff'].agg({'RecencyAgg': np.min}) F_Agg = df.groupby(by=['user_email','product_name'])['ptdate'].agg({'FrequencyAgg': np.size}) M_Agg = df.groupby(by=['user_email','product_name'])['totalcost'].agg({'MonetaryAgg': np.sum}) aggData = R_Agg.join(F_Agg).join(M_Agg) bins = aggData.RecencyAgg.quantile(q=[0, 0.2, 0.4, 0.6, 0.8, 1],interpolation='nearest')
bins[0] = 0
labels = [5, 4, 3, 2, 1]
R_S = pd.cut(aggData.RecencyAgg, bins, labels=labels) #
bins = aggData.FrequencyAgg.quantile(q=[0, 0.2, 0.4, 0.6, 0.8, 1],interpolation='nearest')
bins[0] = 0
labels = [1, 2, 3, 4, 5]
F_S = pd.cut(aggData.FrequencyAgg, bins, labels=labels) bins = aggData.MonetaryAgg.quantile(q=[0, 0.2, 0.4, 0.6, 0.8, 1],interpolation='nearest')
bins[0] = 0
labels = [1, 2, 3, 4, 5]
M_S = pd.cut(aggData.MonetaryAgg,bins, labels=labels) aggData['R_S']=R_S
aggData['F_S']=F_S
aggData['M_S']=M_S aggData['RFM'] = 100*R_S.astype(int) + 10*F_S.astype(int) + 1*M_S.astype(int) 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'] = pd.cut(aggData.RFM, bins, labels=labels) aggData = aggData.reset_index() fe = aggData.sort_values(['level', 'RFM'], ascending=[0, 0]) dd=aggData.groupby(by=['level'])['user_email','product_name'].agg({'size':np.size}) print(fe.head())
fe.to_csv('./rfm_data.csv',index=False)
print("---------------")
print(dd)
# -*- coding: utf-8 -*- '''
描述:案例-基于RFM的用户价值度模型
程序输入:sales.csv
程序输出:RFM得分数据写本地文件sales_rfm_score.csv和数据表(sales_rfm_score)
'''
# 导入库
import time # 导入时间库
import numpy as np # 导入numpy库
import pandas as pd # 导入pandas库
import mysql.connector # 导入mysql连接库 # 读取数据
dtypes = {'ORDERDATE': object, 'ORDERID': object, 'AMOUNTINFO': np.float32} # 设置每列数据类型
raw_data = pd.read_csv('sales.csv', dtype=dtypes, index_col='USERID') # 读取数据文件 # 数据审查和校验
# 数据概览
print ('Data Overview:')
print (raw_data.head(4)) # 打印原始数据前4条
print ('-' * 30)
print ('Data DESC:')
print (raw_data.describe()) # 打印原始数据基本描述性信息
print ('-' * 60) # 缺失值审查
na_cols = raw_data.isnull().any(axis=0) # 查看每一列是否具有缺失值
print ('NA Cols:')
print (na_cols) # 查看具有缺失值的列
print ('-' * 30)
na_lines = raw_data.isnull().any(axis=1) # 查看每一行是否具有缺失值
print ('NA Recors:')
print ('Total number of NA lines is: {0}'.format(na_lines.sum())) # 查看具有缺失值的行总记录数
print (raw_data[na_lines]) # 只查看具有缺失值的行信息
print ('-' * 60) # 数据异常、格式转换和处理
# 异常值处理
sales_data = raw_data.dropna() # 丢弃带有缺失值的行记录
sales_data = sales_data[sales_data['AMOUNTINFO'] > 1] # 丢弃订单金额<=1的记录 # 日期格式转换
sales_data['ORDERDATE'] = pd.to_datetime(sales_data['ORDERDATE'], format='%Y-%m-%d') # 将字符串转换为日期格式
print ('Raw Dtypes:')
print (sales_data.dtypes) # 打印输出数据框所有列的数据类型
print ('-' * 60) # 数据转换
recency_value = sales_data['ORDERDATE'].groupby(sales_data.index).max() # 计算原始最近一次订单时间
frequency_value = sales_data['ORDERDATE'].groupby(sales_data.index).count() # 计算原始订单频率
monetary_value = sales_data['AMOUNTINFO'].groupby(sales_data.index).sum() # 计算原始订单总金额 # 计算RFM得分
# 分别计算R、F、M得分
deadline_date = pd.datetime(2017, 01, 01) # 指定一个时间节点,用于计算其他时间与该时间的距离
r_interval = (deadline_date - recency_value).dt.days # 计算R间隔
r_score = pd.cut(r_interval, 5, labels=[5, 4, 3, 2, 1]) # 计算R得分
f_score = pd.cut(frequency_value, 5, labels=[1, 2, 3, 4, 5]) # 计算F得分
m_score = pd.cut(monetary_value, 5, labels=[1, 2, 3, 4, 5]) # 计算M得分 # R、F、M数据合并
rfm_list = [r_score, f_score, m_score] # 将r、f、m三个维度组成列表
rfm_cols = ['r_score', 'f_score', 'm_score'] # 设置r、f、m三个维度列名
rfm_pd = pd.DataFrame(np.array(rfm_list).transpose(), dtype=np.int32, columns=rfm_cols,
index=frequency_value.index) # 建立r、f、m数据框
print ('RFM Score Overview:')
print (rfm_pd.head(4))
print ('-' * 60) # 计算RFM总得分
# 方法一:加权得分
rfm_pd['rfm_wscore'] = rfm_pd['r_score'] * 0.6 + rfm_pd['f_score'] * 0.3 + rfm_pd['m_score'] * 0.1
# 方法二:RFM组合
rfm_pd_tmp = rfm_pd.copy()
rfm_pd_tmp['r_score'] = rfm_pd_tmp['r_score'].astype('string')
rfm_pd_tmp['f_score'] = rfm_pd_tmp['f_score'].astype('string')
rfm_pd_tmp['m_score'] = rfm_pd_tmp['m_score'].astype('string')
rfm_pd['rfm_comb'] = rfm_pd_tmp['r_score'].str.cat(rfm_pd_tmp['f_score']).str.cat(rfm_pd_tmp['m_score']) # 打印输出和保存结果
# 打印结果
print ('Final RFM Scores Overview:')
print (rfm_pd.head(4)) # 打印数据前4项结果
print ('-' * 30)
print ('Final RFM Scores DESC:')
print (rfm_pd.describe()) # 保存RFM得分到本地文件
rfm_pd.to_csv('sales_rfm_score.csv') # 保存数据为csv # 保存RFM得分到MySQL数据库
# 设置要写库的数据库连接信息
table_name = 'sales_rfm_score' # 要写库的表名
# 数据库基本信息
config = {'host': '127.0.0.1', # 默认127.0.0.1
'user': 'root', # 用户名
'password': '', # 密码
'port': 3306, # 端口,默认为3306
'database': 'python_data', # 数据库名称
'charset': 'gb2312' # 字符编码
}
con = mysql.connector.connect(**config) # 建立mysql连接
cursor = con.cursor() # 获得游标
# 查找数据库是否存在目标表,如果没有则新建
cursor.execute("show tables") #
table_object = cursor.fetchall() # 通过fetchall方法获得所有数据
table_list = [] # 创建库列表
for t in table_object: # 循环读出所有库
table_list.append(t[0]) # 每个每个库追加到列表
if not table_name in table_list: # 如果目标表没有创建
cursor.execute('''
CREATE TABLE %s (
userid VARCHAR(20),
r_score int(2),
f_score int(2),
m_score int(2),
rfm_wscore DECIMAL(10,2),
rfm_comb VARCHAR(10),
insert_date VARCHAR(20)
)ENGINE=InnoDB DEFAULT CHARSET=gb2312
''' % table_name) # 创建新表
# 将数据写入数据库
user_id = rfm_pd.index # 索引列
rfm_wscore = rfm_pd['rfm_wscore'] # RFM加权得分列
rfm_comb = rfm_pd['rfm_comb'] # RFM组合得分列
timestamp = time.strftime('%Y-%m-%d', time.localtime(time.time())) # 写库日期
print ('Begin to insert data into table {0}...'.format(table_name)) # 输出开始写库的提示信息
for i in range(rfm_pd.shape[0]): # 设置循环次数并依次循环
insert_sql = "INSERT INTO `%s` VALUES ('%s',%s,%s,%s,%s,'%s','%s')" % \
(table_name, user_id[i], r_score.iloc[i], f_score.iloc[i], m_score.iloc[i], rfm_wscore.iloc[i],
rfm_comb.iloc[i], timestamp) # 写库SQL依据
cursor.execute(insert_sql) # 执行SQL语句,execute函数里面要用双引号
con.commit() # 提交命令
cursor.close() # 关闭游标
con.close() # 关闭数据库连接
print ('Finish inserting, total records is: %d' % (i + 1)) # 打印写库结果
第三版
import pandas as pd
import numpy as np df = pd.read_excel('./zue_edu.xlsx',sheet_name='Q2未消费的',index_col='user_id')
df['ptdate'] = pd.to_datetime(df['ptdate'],format='%Y-%m-%d') recency_value = df['ptdate'].groupby(df['product_name']).max() # 计算原始最近一次订单时间
r_interval = (pd.to_datetime('2019-05-06',format='%Y-%m-%d') - recency_value).dt.days # 计算R间隔
frequency_value = df['ptdate'].groupby([df['user_email'],df['product_name']]).count() # 计算原始订单频率
monetary_value = df['cost'].groupby(df['product_name']).sum() # 计算原始订单总金额
frequency_value = frequency_value.groupby('product_name').max() data_list = [recency_value,r_interval, frequency_value, monetary_value]
data_pd = pd.DataFrame(np.array(data_list).transpose(), columns=['上次消费时间','已停投天数', '有消费天数', '消费金额'] ,
index=frequency_value.index) # 建立原始数据框 # 计算RFM得分
# 分别计算R、F、M得分
r_score = pd.cut(r_interval, 5, labels=[5, 4, 3, 2, 1]) # 计算R得分
f_score = pd.cut(frequency_value, 5, labels=[1, 2, 3, 4, 5]) # 计算F得分
m_score = pd.cut(monetary_value, 5, labels=[1, 2, 3, 4, 5]) # 计算M得分 # R、F、M数据合并
rfm_list = [r_score, f_score, m_score] # 将r、f、m三个维度组成列表
rfm_cols = ['r_score', 'f_score', 'm_score'] # 设置r、f、m三个维度列名
rfm_pd = pd.DataFrame(np.array(rfm_list).transpose(), dtype=np.int32, columns=rfm_cols,
index=frequency_value.index) # 建立r、f、m数据框 # 计算RFM总得分
# 方法一:加权得分
rfm_pd['rfm_wscore'] = rfm_pd['r_score'] * 0.6 + rfm_pd['f_score'] * 0.3 + rfm_pd['m_score'] * 0.1 # 方法二:RFM组合
rfm_pd_tmp = rfm_pd.copy()
rfm_pd_tmp['r_score'] = rfm_pd_tmp['r_score'].astype('str')
rfm_pd_tmp['f_score'] = rfm_pd_tmp['f_score'].astype('str')
rfm_pd_tmp['m_score'] = rfm_pd_tmp['m_score'].astype('str')
rfm_pd['rfm_comb'] = rfm_pd_tmp['r_score'].str.cat(rfm_pd_tmp['f_score']).str.cat(rfm_pd_tmp['m_score']) rfm_pd['rfm_comb'] = rfm_pd['rfm_comb'].astype('int') rfm_pd['最近级别'] = rfm_pd['r_score'].replace({5:'优',4:'良',3:'一般',2:'差',1:'非常差'})
rfm_pd['频次'] = rfm_pd['f_score'].replace({5:'优',4:'良',3:'一般',2:'差',1:'非常差'})
rfm_pd['金额'] = rfm_pd['m_score'].replace({5:'优',4:'良',3:'一般',2:'差',1:'非常差'}) bins = rfm_pd.rfm_wscore.quantile(q=[0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1],interpolation='nearest')
bins[0] = 0 #起点为0
labels = [1, 2, 3, 4, 5, 6, 7, 8]
rfm_pd['level'] = pd.cut(rfm_pd.rfm_wscore, bins, labels=labels) rfm_pd = rfm_pd.reset_index()
data_pd = data_pd.reset_index()
fe = rfm_pd.sort_values('rfm_comb', ascending=0)
fina = fe.merge(data_pd,on='product_name') # 打印结果
print(fina.head())
fina.to_excel('./rfm_edu_Q2non.xlsx',index=False)
pandas 实现rfm模型的更多相关文章
- RFM模型的变形LRFMC模型与K-means算法的有机结合
应用场景: 可以应用在不同行业的客户分类管理上,比如航空公司,传统的RFM模型不再适用,通过RFM模型的变形LRFMC模型实现客户价值分析:基于消费者数据的精细化营销 应用价值: LRFMC模型构建之 ...
- 案例(一) 利用机器算法RFM模型做用户价值分析
一.案例背景 在产品迭代过程中,通常需要根据用户的属性进行归类,也就是通过分析数据,对用户进行归类,以便于在推送及转化过程中获得更大的收益. 本案例是基于某互联网公司的实际用户购票数据为研究对象, ...
- RFM模型——构建数据库营销的商业战役!(转)
RFM模型:R(Recency)表示客户最近一次购买的时间有多远,F(Frequency)表示客户在最近一段时间内购买的次数,M (Monetary)表示客户在最近一段时间内购买的金额.一般原始数据为 ...
- 数据挖掘应用案例:RFM模型分析与客户细分(转)
正好刚帮某电信行业完成一个数据挖掘工作,其中的RFM模型还是有一定代表性,就再把数据挖掘RFM模型的建模思路细节与大家分享一下吧!手机充值业务是一项主要电信业务形式,客户的充值行为记录正好满足RFM模 ...
- RFM模型及R语言实现
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 一.基本概念 根据美国数据库营销研究所Arth ...
- 使用ML.NET实现基于RFM模型的客户价值分析
RFM模型 在众多的客户价值分析模型中,RFM模型是被广泛应用的,尤其在零售和企业服务领域堪称经典的分类手段.它的核心定义从基本的交易数据中来,借助恰当的聚类算法,反映出对客户较为直观的分类指示,对于 ...
- RFM模型
python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...
- 为啥我做的RFM模型被人说做错了,我错哪了?
本文转自知乎 作者:接地气的陈老师 ————————————————————————————————————————————————————— 有同学问:“为啥我做的RFM模型被客户/业务部门批斗,说 ...
- RFM模型的应用 - 电商客户细分(转)
RFM模型是网点衡量当前用户价值和客户潜在价值的重要工具和手段.RFM是Rencency(最近一次消费),Frequency(消费频率).Monetary(消费金额) 消费指的是客户在店铺消费最近一次 ...
随机推荐
- FD.io 社区中国行暨未来网络技术沙龙 南京站 参会小结
FD.io 社区中国行暨未来网络技术沙龙 南京站,2018 年 3 月 17 日. 开场致辞 Ray 介绍了一些有的没的 ⁃ (Future Event)DPDK summit, FD.io summ ...
- 课堂alpha发布
项目组名:奋斗吧兄弟 今天七组对于各自项目现有的成果进行了alpha发布,下面是我的一些感想. 天天向上团队的连连看游戏: 令我印象最深的是天天向上团队的连连看项目,他们目前能展示给我们的是核心的连连 ...
- Python网络爬虫(1)--url访问及参数设置
环境:Python2.7.9 / Sublime Text 2 / Chrome 1.url访问,直接调用urllib库函数即可 import urllib2 url='http://www.baid ...
- [知乎]老狼:深入PCI与PCIe之二:软件篇
深入PCI与PCIe之二:软件篇 https://zhuanlan.zhihu.com/p/26244141 我们前一篇文章(深入PCI与PCIe之一:硬件篇 - 知乎专栏)介绍了PCI和PCIe的硬 ...
- js获取元素到屏幕左上角的距离
开发过程中经常会遇到 获取元素到屏幕左上角的距离, 当我们使用jQuery开发时,我们可以使用 $.offset()来获取准确的距离. 如果我们的项目中并没有引入jQuer的话,跟希望通过原生方法实现 ...
- BZOJ5305 HAOI2018苹果树(概率期望+动态规划)
每种父亲编号小于儿子编号的有标号二叉树的出现概率是相同的,问题相当于求所有n个点的此种树的所有结点两两距离之和. 设f[n]为答案,g[n]为所有此种树所有结点的深度之和,h[n]为此种树的个数. 枚 ...
- Trailing Zeroes (I) LightOJ - 1028(求因子个数)
题意: 给出一个N 求N有多少个别的进制的数有后导零 解析: 对于一个别的进制的数要转化为10进制 (我们暂且只分析二进制就好啦) An * 2^(n-1) + An-1 * 2^(n-2) + `` ...
- 利用VRID/VMAC实现更安全的netscaler HA故障切换
利用VRID/VMAC实现更安全的netscaler HA故障切换 virtual MAC在故障切换(failover)中的作用. 在一个HA模式中,首要节点(primary node)拥有所有 ...
- 使用jQuery在javascript中自定义事件
js中的自定义事件有attachEvent,addEventListener等等好多种,往往受困于浏览器兼容,而且代码写起来也相当麻烦.jQuery为我们解决了这个问题,几行代码就可以很好的实现事件的 ...
- BZOJ 2745: [HEOI2012]Bridge
2745: [HEOI2012]Bridge Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 199 Solved: 90[Submit][Statu ...