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模型的更多相关文章

  1. RFM模型的变形LRFMC模型与K-means算法的有机结合

    应用场景: 可以应用在不同行业的客户分类管理上,比如航空公司,传统的RFM模型不再适用,通过RFM模型的变形LRFMC模型实现客户价值分析:基于消费者数据的精细化营销 应用价值: LRFMC模型构建之 ...

  2. 案例(一) 利用机器算法RFM模型做用户价值分析

      一.案例背景 在产品迭代过程中,通常需要根据用户的属性进行归类,也就是通过分析数据,对用户进行归类,以便于在推送及转化过程中获得更大的收益. 本案例是基于某互联网公司的实际用户购票数据为研究对象, ...

  3. RFM模型——构建数据库营销的商业战役!(转)

    RFM模型:R(Recency)表示客户最近一次购买的时间有多远,F(Frequency)表示客户在最近一段时间内购买的次数,M (Monetary)表示客户在最近一段时间内购买的金额.一般原始数据为 ...

  4. 数据挖掘应用案例:RFM模型分析与客户细分(转)

    正好刚帮某电信行业完成一个数据挖掘工作,其中的RFM模型还是有一定代表性,就再把数据挖掘RFM模型的建模思路细节与大家分享一下吧!手机充值业务是一项主要电信业务形式,客户的充值行为记录正好满足RFM模 ...

  5. RFM模型及R语言实现

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 一.基本概念 根据美国数据库营销研究所Arth ...

  6. 使用ML.NET实现基于RFM模型的客户价值分析

    RFM模型 在众多的客户价值分析模型中,RFM模型是被广泛应用的,尤其在零售和企业服务领域堪称经典的分类手段.它的核心定义从基本的交易数据中来,借助恰当的聚类算法,反映出对客户较为直观的分类指示,对于 ...

  7. RFM模型

    python信用评分卡(附代码,博主录制) https://study.163.com/course/introduction.htm?courseId=1005214003&utm_camp ...

  8. 为啥我做的RFM模型被人说做错了,我错哪了?

    本文转自知乎 作者:接地气的陈老师 ————————————————————————————————————————————————————— 有同学问:“为啥我做的RFM模型被客户/业务部门批斗,说 ...

  9. RFM模型的应用 - 电商客户细分(转)

    RFM模型是网点衡量当前用户价值和客户潜在价值的重要工具和手段.RFM是Rencency(最近一次消费),Frequency(消费频率).Monetary(消费金额) 消费指的是客户在店铺消费最近一次 ...

随机推荐

  1. CodeM Qualifying Match Q1

    问题描述: 具体地说,就是在第二段音频中找到一个长度和第一段音频相等且是连续的子序列,使得它们的 difference 最小.两段等长音频的 difference 定义为: difference = ...

  2. Java网络编程一:基础知识详解

    网络基础知识 1.OSI分层模型和TCP/IP分层模型的对应关系 这里对于7层模型不展开来讲,只选择跟这次系列主题相关的知识点介绍. 2.七层模型与协议的对应关系 网络层   ------------ ...

  3. ABP ModuleZero 添加角色_创建角色是报错的问题解决方案

    ABP升级后,大概3.6.1以后,在.net framework里面,从官方下载的Module zero模板添加角色是出现下面错误. 这个问题,算是新版apb的一点小缺憾,好像在.net core的模 ...

  4. 深入理解JAVA虚拟机阅读笔记2——垃圾回收

    线程私有的程序计数器.虚拟机栈和本地方法栈随线程而生,随线程而灭.栈中的栈帧随方法的进入和退出有条不紊的入栈和出栈. 而Java堆和方法区因为需要多大内存.创建多少对象都是不确定的,因此这两个区域是垃 ...

  5. JAVA LOG4J使用方法

    首先,需要在项目中导入log4j使用的JAR包,导入结果如下图: 菜单:Build Path->Configure Build Path->Add Extern Jars 导入JAR包后, ...

  6. requestAnimationFrame 优雅降级

    if (!Date.now) Date.now = function() { return new Date().getTime(); }; (function() { 'use strict'; v ...

  7. PE文件解析 基础篇

    PE文件解析 基础篇 来源 https://bbs.pediy.com/thread-247114.htm 前言 之前学习了PE格式,为了更好的理解,决定写一个类似LoadPE的小工具. 编译器是VS ...

  8. Alpha 冲刺 —— 十分之三

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助后端界面的开发 搭建项目运行的服务器环境 ...

  9. 洛谷 P1850 换教室 解题报告

    P1850 换教室 题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有\(2n\)节课程安排在\(n\)个时间段上.在第\(i(1≤i≤n) ...

  10. 洛谷 P1783 海滩防御 解题报告

    P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...