Customer segmentation – LifeCycle Grids, CLV and CAC with R(转)
We studied a very powerful approach for customer segmentation in the previous post, which is based on the customer’s lifecycle. We used two metrics: frequency and recency. It is also possible and very helpful to add monetary value to our segmentation. If you havecustomer acquisition cost (CAC) and customer lifetime value (CLV), you can easily add these data to the calculations.
We will create the same data sample as in the previous post, but with two added data frames:
- cac, our expenses for each customer acquisition,
- gr.margin, gross margin of each product.
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# loading librarieslibrary(dplyr)library(reshape2)library(ggplot2)# creating data sampleset.seed(10)data <- data.frame(orderId=sample(c(1:1000), 5000, replace=TRUE),product=sample(c('NULL','a','b','c'), 5000, replace=TRUE,prob=c(0.15, 0.65, 0.3, 0.15)))order <- data.frame(orderId=c(1:1000),clientId=sample(c(1:300), 1000, replace=TRUE))gender <- data.frame(clientId=c(1:300),gender=sample(c('male', 'female'), 300, replace=TRUE, prob=c(0.40, 0.60)))date <- data.frame(orderId=c(1:1000),orderdate=sample((1:100), 1000, replace=TRUE))orders <- merge(data, order, by='orderId')orders <- merge(orders, gender, by='clientId')orders <- merge(orders, date, by='orderId')orders <- orders[orders$product!='NULL', ]orders$orderdate <- as.Date(orders$orderdate, origin="2012-01-01")# creating data frames with CAC and Gross margincac <- data.frame(clientId=unique(orders$clientId), cac=sample(c(10:15), 289, replace=TRUE))gr.margin <- data.frame(product=c('a', 'b', 'c'), grossmarg=c(1, 2, 3))rm(data, date, order, gender) |
Next, we will calculate CLV to date (actual amount that we earned) using gross margin values and orders of the products. We will use the following code:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
# reporting datetoday <- as.Date('2012-04-11', format='%Y-%m-%d')# calculating customer lifetime valueorders <- merge(orders, gr.margin, by='product')clv <- orders %>%group_by(clientId) %>%summarise(clv=sum(grossmarg))# processing dataorders <- dcast(orders, orderId + clientId + gender + orderdate ~ product, value.var='product', fun.aggregate=length)orders <- orders %>%group_by(clientId) %>%mutate(frequency=n(),recency=as.numeric(today-orderdate)) %>%filter(orderdate==max(orderdate)) %>%filter(orderId==max(orderId))orders.segm <- orders %>%mutate(segm.freq=ifelse(between(frequency, 1, 1), '1',ifelse(between(frequency, 2, 2), '2',ifelse(between(frequency, 3, 3), '3',ifelse(between(frequency, 4, 4), '4',ifelse(between(frequency, 5, 5), '5', '>5')))))) %>%mutate(segm.rec=ifelse(between(recency, 0, 6), '0-6 days',ifelse(between(recency, 7, 13), '7-13 days',ifelse(between(recency, 14, 19), '14-19 days',ifelse(between(recency, 20, 45), '20-45 days',ifelse(between(recency, 46, 80), '46-80 days', '>80 days')))))) %>%# creating last cart featuremutate(cart=paste(ifelse(a!=0, 'a', ''),ifelse(b!=0, 'b', ''),ifelse(c!=0, 'c', ''), sep='')) %>%arrange(clientId)# defining order of boundariesorders.segm$segm.freq <- factor(orders.segm$segm.freq, levels=c('>5', '5', '4', '3', '2', '1'))orders.segm$segm.rec <- factor(orders.segm$segm.rec, levels=c('>80 days', '46-80 days', '20-45 days', '14-19 days', '7-13 days', '0-6 days')) |
Note: if you prefer to use potential/expected/predicted CLV or total CLV (sum of CLV to date and potential CLV) you can adapt this code or find the example in the next post.
In addition, we need to merge orders.segm with the CAC and CLV data, and combine the data with the segments. We will calculate total CAC and CLV to date, as well as their average with the following code:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
orders.segm <- merge(orders.segm, cac, by='clientId')orders.segm <- merge(orders.segm, clv, by='clientId')lcg.clv <- orders.segm %>%group_by(segm.rec, segm.freq) %>%summarise(quantity=n(),# calculating cumulative CAC and CLVcac=sum(cac),clv=sum(clv)) %>%ungroup() %>%# calculating CAC and CLV per clientmutate(cac1=round(cac/quantity, 2),clv1=round(clv/quantity, 2))lcg.clv <- melt(lcg.clv, id.vars=c('segm.rec', 'segm.freq', 'quantity')) |
Ok, let’s plot two charts: the first one representing the totals and the second one representing the averages:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
ggplot(lcg.clv[lcg.clv$variable %in% c('clv', 'cac'), ], aes(x=variable, y=value, fill=variable)) +theme_bw() +theme(panel.grid = element_blank())+geom_bar(stat='identity', alpha=0.6, aes(width=quantity/max(quantity))) +geom_text(aes(y=value, label=value), size=4) +facet_grid(segm.freq ~ segm.rec) +ggtitle("LifeCycle Grids - CLV vs CAC (total)")ggplot(lcg.clv[lcg.clv$variable %in% c('clv1', 'cac1'), ], aes(x=variable, y=value, fill=variable)) +theme_bw() +theme(panel.grid = element_blank())+geom_bar(stat='identity', alpha=0.6, aes(width=quantity/max(quantity))) +geom_text(aes(y=value, label=value), size=4) +facet_grid(segm.freq ~ segm.rec) +ggtitle("LifeCycle Grids - CLV vs CAC (average)") |


You can find in the grid that the width of bars depends on the number of customers. I think these visualizations are very helpful. You can see the difference between CLV to dateand CAC and make decisions about on paid campaigns or initiatives like:
- does it make sense to spend extra money to reactivate some customers (e.g. those who are in the “1 order / >80 days“ grid or those who are in the “>5 orders / 20-45 days“ grid)?,
- how much money is appropriate to spend?,
- and so on.
Therefore, we have got a very interesting visualization. We can analyze and make decisions based on the three customer lifecycle metrics: recency, frequency andmonetary value.
Thank you for reading this!
转自:http://analyzecore.com/2015/02/19/customer-segmentation-lifecycle-grids-clv-and-cac-with-r/
Customer segmentation – LifeCycle Grids, CLV and CAC with R(转)的更多相关文章
- Customer segmentation – LifeCycle Grids with R(转)
I want to share a very powerful approach for customer segmentation in this post. It is based on cust ...
- Cohort Analysis and LifeCycle Grids mixed segmentation with R(转)
This is the third post about LifeCycle Grids. You can find the first post about the sense of LifeCyc ...
- Appboy 基于 MongoDB 的数据密集型实践
摘要:Appboy 正在过手机等新兴渠道尝试一种新的方法,让机构可以与顾客建立更好的关系,可以说是市场自动化产业的一个前沿探索者.在移动端探索上,该公司已经取得了一定的成功,知名产品有 iHeartM ...
- ML.NET教程之客户细分(聚类问题)
理解问题 客户细分需要解决的问题是按照客户之间的相似特征区分不同客户群体.这个问题的先决条件中没有可供使用的客户分类列表,只有客户的人物画像. 数据集 已有的数据是公司的历史商业活动记录以及客户的购买 ...
- CRM 建设方案(01):CRM基础
CRM 客户关系管理系统基础 客户关系管理简称CRM(Customer Relationship Management).CRM概念引入中国已有数年,其字面意思是客户关系管理,但其深层的内涵却有着许多 ...
- python excel 文件合并
Combining Data From Multiple Excel Files Introduction A common task for python and pandas is to auto ...
- Ninject之旅之六:Ninject约定
摘要 在小的应用系统中一个一个注册一些服务类型不怎么困难.但是,如果是一个实际的有上百个服务的应用程序呢?约定配置允许我们使用约定绑定一组服务,而不用一个一个分别绑定. 要使用约定配置,需要添加Nin ...
- 沈阳润才教育CRM
一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...
- python 全栈开发,Day107(CRM初始,权限组件之权限控制,权限系统表设计)
一.CRM初始 CRM,客户关系管理系统(Customer Relationship Management).企业用CRM技术来管理与客户之间的关系,以求提升企业成功的管理方式,其目的是协助企业管理销 ...
随机推荐
- 2 Java对象的创建过程
JAVA中创建对象直接new创建一个对象,对么对象的创建过程是怎样的呢? 程序运行过程中有许多的对象被创建出来.那么对象是如何创建的呢? 一 对象创建的步骤 1 遇到new指令时,检查这个指令的参数是 ...
- day002-HTML知识点总结:浏览器兼容性之指定IE浏览器使用chrome内核渲染页面
今天再浏览大淘宝首页时,突然看到这么一个东东: ,顿时好费解,莫非万恶的IE浏览器认识到自己以往的罪孽,开始兼容chrome了??! 于是本着不懂就百度的神精,开始纵横于各大铁耙,勃哥,终于找到了许许 ...
- mysqldumpslow的使用简介
mysqldumpslow的使用:比如我们要查询按时间返回前5条日志信息,格式如下:mysqldumpslow -s t -t 5 /var/log/mysql/slowquery_20170303. ...
- Linux轻松使用vim
VIM命令---Vi IMproved, a programmers text editor文本编辑 1>gedit 图形文本编辑工具 2>vim 字符界面的编辑工具 写脚本 ...
- Java 别名(Aliasing)
别名 (Aliasing) 别名,顾名思义,是有别于现在名字的另一个名字,但指的是不是同一个人或事物呢?比如,你上学的时候同学有没有给你起什么外号?如果有的话,你的名字和同学给你起的外号是不是都指的是 ...
- java8 Lambda表达式的新手上车指南(1)
背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...
- 各种 SVG 制作单选和多选框动画
在线演示 源码下载
- Html5浏览器支持
HTML5 浏览器支持 把 HTML5 元素定义为块级元素 语义块级displayblock实例 header, section, footer, aside, nav, main, article, ...
- H5前端框架推荐合集
Ionic ionic 吧开发流程都帮你做好了,已经不再是单纯的UI框架,而是开发框架了,非常适合快速开发.基于angular2,丰富的UI组件,大大改进的编程模型, Semantic UI 中文官网 ...
- 一条sql语句引发mysql不停创建临时表的问题解决..coping to tmp table on desk
(不懂临时表的先看 MySQL临时表 ) 首先,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间.因此在不同的连接中可以创建同名的临时表,并且操作属于本连接的临时表. ...