客户终身价值(CLTV)计算和回归预测模型(Python)

news2024/11/19 0:51:42

内容介绍

本文整理了客户终身价值(CLV或者CLTV)的相关概念,并对一家英国线上零售公司的一年交易数据进行分析,计算该公司所有客户的CLV并且建立回归预测模型。

一、客户生命周期价值

用户生命周期价值Customer Lifetime value(缩写是CLV 或者CLTV), 也有称为Lifetime Value(LTV),值得是在客户整个生命周期中企业能获得的总价值。

CLV 与 LTV 有什么区别?

多数情况下二者没有区别,比较模糊的情况下是:LTV不包括成本,而CLV是扣掉成本后的利润。

比如在互联网行业、APP、移动广告等业务中,使用的公式是:
LTV=LT(活跃天数)*ARPU(用户每次活跃产生的价值)
同时LTV还会结合CAC(获客成本Customer acquisition cost)一起分析,CAC公式如下:
CAC=总市场花费/对应花费带来的总新用户数

可见在这个场景中LTV是计算用户支出的总金额(不包括成本)。

比如这篇文章认为LTV是总收入,而CLV是利润(去掉成本), 并且使用具体的例子解释。
在这里插入图片描述
另外一篇文章中的CLV计算则是用的总收入。
在这里插入图片描述

如何计算CLV?

比如一个客户每年都在会在一家商店里买东西,每个月花200元,一共有10年时间在这家店消费。那么对于这家商店而言,这个客户的终身价值就是他在店里一共消费的金额,即200*12*10=24000元

1. CLV计算公式

在实际商业分析中,仅仅分析一个客户是没有意义的,一般是要去计算整个企业、或者不同产品、地区的CLV。由上面单个用户的计算过成,可以推导出:

客户终身价值(CLV)=客户价值(Customer Value) * 平均客户生命周期(Average Customer Lifespan)

其中,
客户价值(Customer Value)=平均支付金额(Average purchase value)*平均支付次数(Average purchase frequency)

  • 平均支付金额(Average purchase value)= 总收入(Total Revenue) /总订单数(Total Number of Orders)
  • 平均支付次数(Average purchase frequency)=总订单数(Total Number of Orders)/总客户数(Total Number of Customers)

客户的生命周期比较难预估,尤其是新的企业,可能没有足够的时间去观察平均的客户生命周期。
**客户生命周期(Customer Lifetime)**=1/Churn Rate
其中,

  • 客户流失率(Churn Rate): 流失用户数/总用户数=1-留存率
  • 客户留存率(Repeat Rate) : 留存用户数/总用户数

2.历史CLV计算公式

就是前面提到过的公式,常用于游戏、APP等互联网业务数据分析中:
CLV=LT(活跃天数)*ARPU(用户每次活跃产生的价值)
这种方法根据企业过去的毛利润来计算客户的生命周期价值,很简单直接。

3.传统 CLV 计算方法

因为业务增长是波动变化的,客户的支付总金额不可能一成不变,客户数量也在不断变化,还要考虑到通货膨胀的影响,传统的CLV计算公式为:

在这里插入图片描述
此计算涉及一些额外的概念:

  • GML——每个客户生命周期的毛利率(gross margin per customer lifespan): 这是期望在平均客户生命周期内赚取的利润(即收入减去成本)
  • R——留存率(Retention Rate): 在设定的时间段内留在您身边的客户百分比(相对于在那段时间内流失的客户)
  • D——贴现率(Discount Rate): 考虑通货膨胀的百分比。这通常设置为 10%。

更多的计算方法可以参考这篇文章

CLV预测方法

这里简单介绍两种方法。

1. 直接估计

客户每年支付总金额*客户关系时长-总获客/服务成本
直接根据经验或者历史数据去预估各项数据,比如:

  • 过去三年的平均收入是500元,
  • 客户关系维持时间是5年,即5年的生命,
  • 获客成本 50元
  • 服务成本每年10元
    CLV=500*5-50-10*5=2500-100=2400(元)

2. 基于历史数据建立预测模型

现存客户CLV预测模型,根据历史数据对未来的一个时间进行预测,可以使用近6个月或者过去三年的数据进行数据建模,求出下面这个拟合公式的各项参数:
在这里插入图片描述

二、客户价值CLV计算

数据集简介

数据集包含一家在英国注册的在线零售公司于 01/12/2010 和 09/12/2011 之间发生的所有交易。该公司主要销售各种场合的礼品,公司的许多客户都是批发商。

数据集一共包含8列:

  • InvoiceNo:发票编号。标称,为每笔交易唯一分配的 6 位整数。如果此代码以字母“c”开头,则表示取消。
  • StockCode:商品(商品)代码。标称,为每个不同的产品唯一分配的 5 位整数。
  • Description: 描述。 产品(项目)名称。
  • Quantity:数量。每笔交易每个产品(项目)的数量。
  • InvoiceDate:发票日期和时间,每笔交易产生的日期和时间。
  • UnitPrice:单价,单位产品价格(以英镑为单位)。
  • CustomerID:客户编号,一个唯一分配给每个客户的 5 位整数。
  • Country:国名,每个客户所在国家/地区的名称。

数据导入

#导入包
import pandas as pd 
import matplotlib.pyplot as plt 
import seaborn as sns 
import datetime as dt
import numpy as np

#数据读取
data=pd.read_excel('Online Retail.xlsx', parse_dates=['InvoiceDate'])

#查看数据
data.head()

在这里插入图片描述

处理异常值

# 查看数据分布
data.describe()

在这里插入图片描述

数据集中的数量Quantity和价格中包含异常的负数,应是属于取消订单,但这里先当作异常值直接删除。

#filter
data = data[(data['Quantity']>0)&(data['UnitPrice']>0)]
data.describe()

在这里插入图片描述

处理缺失值

# 查看缺失情况
data.isnull().sum()

![[Pasted image 20221221221220.png]]
用户ID有很多缺失值,这里也直接处理掉。

#删除缺失值
data=data.dropna()
#检查结果
data.isnull().sum() 

计算总金额

#Calulate total purchase
data['TotalPurchase'] = data['Quantity'] * data['UnitPrice']

查看国家和客户的分布情况

#删除重复数据
filtered_data=data[['Country','CustomerID']].drop_duplicates()

#查看前十个最多客户的国家 
filtered_data.Country.value_counts()[:10].plot(kind='bar')

![[Pasted image 20221221190539.png]]
图上可以见,用户主要集中在UK,所以我们先分析UK的客户。

uk_data=data[data.Country=='United Kingdom']
uk_data.info()

在这里插入图片描述

#选取需要的数据列
uk_data=uk_data[['CustomerID','InvoiceDate','InvoiceNo','Quantity','UnitPrice','TotalPurchase']]

# 根据客户ID分组,分别计算出最近消费时间、总消费单数和总消费金额
uk_data_group=uk_data.groupby('CustomerID').agg({'InvoiceDate': lambda date: (date.max() - date.min()).days,
                                        'InvoiceNo': lambda num: len(num),
                                        'Quantity': lambda quant: quant.sum(),
                                        'TotalPurchase': lambda price: price.sum()})
#重命名
uk_data_group.columns=['num_days','num_transactions','num_units','spent_money']
#查看结果 
uk_data_group.head()

![[Pasted image 20221221221824.png]]

计算CLTV

CLTV = ((Average Order Value x Purchase Frequency)/Churn Rate) x Profit margin. Customer Value = Average Order Value * Purchase Frequency

# Average Order Value
uk_data_group['avg_order_value']=uk_data_group['spent_money']/uk_data_group['num_transactions']

#purchase_frequency
purchase_frequency=sum(uk_data_group['num_transactions'])/uk_data_group.shape[0]

# Repeat Rate
repeat_rate=uk_data_group[uk_data_group.num_transactions > 1].shape[0]/uk_data_group.shape[0]

#Churn Rate
churn_rate=1-repeat_rate

利润率假设

利润率是常用的盈利比率。它代表总销售额的多少百分比作为收益获得。假设我们的业务在总销售额中有大约 5% 的利润。

uk_data_group['profit_margin']=uk_data_group['spent_money']*0.05

#查看结果
uk_data_group.head()

在这里插入图片描述

# Customer Value
uk_data_group['CLV']=(uk_data_group['avg_order_value']*purchase_frequency)/churn_rate

# Customer Lifetime Value
uk_data_group['cust_lifetime_value']=uk_data_group['CLV']*uk_data_group['profit_margin']

在这里插入图片描述

CLTV预测模型

模型训练

#提取年月
uk_data['month_yr'] = uk_data['InvoiceDate'].apply(lambda x: x.strftime('%b-%Y'))

#将数据转置
sale=uk_data.pivot_table(index=['CustomerID'],columns=['month_yr'],values='TotalPurchase',aggfunc='sum',fill_value=0).reset_index()

#计算每个客户的CLV
sale['CLV']=sale.iloc[:,2:].sum(axis=1)

#查看结果
sale.head()

将原数据转换成以客户ID为行,年月为列的数据集。
在这里插入图片描述

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression


#取最近6个月的数据作为特征X,CLV是Y
X=sale[['Dec-2011','Nov-2011', 'Oct-2011','Sep-2011','Aug-2011','Jul-2011']]
y=sale[['CLV']]

#数据集切分
X_train, X_test, y_train, y_test = train_test_split(X, y,random_state=0)

#模型训练
linreg = LinearRegression()
linreg.fit(X_train, y_train)

#结果预测
y_pred = linreg.predict(X_test)

# 打印截距和系数
print(linreg.intercept_)
print(linreg.coef_)

在这里插入图片描述

模型评估

#模型评估
from sklearn import metrics

print("R-Square:",metrics.r2_score(y_test, y_pred))
print("MAE:",metrics.mean_absolute_error(y_test,y_pred))
print("MSE",metrics.mean_squared_error(y_test, y_pred))
print("RMSE:",np.sqrt(metrics.mean_squared_error(y_test, y_pred)))

在这里插入图片描述
R平方介于 0-1 之间,越接近 1,回归拟合效果越好,一般认为 超过 0.8 的模型拟合优度比较高。
该模型的R平方为0.85,因此该模型的拟合效果比较高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107037.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见实用的锁策略详解

🎈专栏链接:多线程相关知识详解 目录 1.乐观锁VS悲观锁 2.读写锁VS普通互斥锁 3.轻量级锁VS重量级锁 4.自旋锁VS挂起等待锁 5. 公平锁VS非公平锁 6.可重入锁VS不可重入锁 7.关于synchronized的锁策略以及自适应 1.乐观锁VS悲观锁 乐观锁:预测锁…

Windows中安装配置RabbitMQ

本次安装环境win10,采用版本 OTP 25.0.3https://github.com/erlang/otp/releases/tag/OTP-25.0.3RabbitMQ 3.10.13 Release RabbitMQ 3.10.13 rabbitmq/rabbitmq-server GitHubOpen source RabbitMQ: core server and tier 1 (built-in) plugins - Release Rabbi…

[N1CTF 2018]eating_cms parse_url绕过

index.php <?php require_once "function.php"; if(isset($_SESSION[login] )){Header("Location: user.php?pageinfo"); } else{include "templates/index.html"; } ?> function.php <?php session_start(); require_once &q…

Kafka Producer 自定义 拦截器 序列化

Kafka Producer 拦截器 & 序列化 前言 文章中的版本信息、maven依赖如下 JDK17 kafka_2.13-3.3.1 pom文件 <dependencies><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>…

NR HARQ (四)Type-2 HARQ-ACK codebook

微信同步更新欢迎关注同名modem协议笔记 上篇提到type-1 HARQ-ACK codebook&#xff0c;即semi-static codebook&#xff0c;UE要为每个PDSCH候选位置生成反馈&#xff0c;也会包含实际没有下行传输的PDSCH&#xff0c;再加上配置CBG的场景&#xff0c;HARQ-ACK 码本中包含的无…

【Linux 内核 内存管理】物理内存组织结构

一、 UMA和NUMA两种模型 共享存储型多处理机有两种模型 一致内存访问&#xff08;Uniform-Memory-Access&#xff0c;简称UMA&#xff09;模型 非一致内存访问&#xff08;Nonuniform-Memory-Access&#xff0c;简称NUMA&#xff09;模型 UMA模型 物理存储器被所有处理器件均…

超标量处理器设计——第八章_发射

超标量处理器设计——第八章_发射 参考《超标量处理器》姚永斌著 文章目录超标量处理器设计——第八章_发射8.1 简述8.1.1 集中式 VS. 分布式8.1.2 数据捕捉 VS. 非数据捕捉8.1.3 压缩 VS. 非压缩8.2 发射过程的流水线8.2.1 非数据捕捉结构的流水线8.2.2 数据捕捉结构的流水线8…

随手写系列——写一个凯撒密码转换页面

文章目录先展示效果H5编写C3编写JS编写——方法一&#xff1a;过程版JS编写——方法二&#xff1a;对象版代码获取先展示效果 &#xff08;因为主要是实现功能&#xff0c;所以CSS写的很粗糙&#xff09; H5编写 基础结构如下&#xff1a; 先构成最外面的大盒子.box&#…

【Flutter】之便于提高开发效率的周边库和轮子

GetX 状态管理 GetX包含很多功能&#xff0c;各种弹出widget、路由管理、国际化、Utils、状态管理等。 基于路由管理 1. 添加到项目中 1.1. 将此添加到pubspec.yaml文件中。 get: 4.1.4 1.2. 在命令行中运行 flutter packages get 1.3. 在MaterialApp前面加上 “Get”&…

centos7 yum安装postgreSQL

安装环境centos7.6 安装步骤&#xff1a; 1、安装postgresql&#xff1a; yum install postgresql-server 2、安装postgresql 扩展包&#xff1a; yum install postgresql-contrib 3、初始化&#xff1a; postgresql-setup initdb 4、启动开机自启动&#xff1a; systemc…

说话人识别神经网络推理方式

概述 说话人识别是一个序列总结&#xff08;Sequence Summarization&#xff09;任务&#xff0c;输入是音频&#xff08;或者说&#xff0c;声学特征的序列&#xff09;&#xff0c;输出是说话人的嵌入码&#xff0c;有的神经网络可以输入一对音频&#xff0c;直接输出这对音…

java微信支付v3系列——9.微信支付之商家转账API

这个功能就比较复杂了&#xff0c;首先是得有90天的资金流水才能开通&#xff0c;其次开通后还需要在官网进行配置&#xff0c;不能直接调用&#xff0c;并且限制了IP地址。 如下图所示&#xff0c;首先需要进行产品设置&#xff0c;将里面都设置好后才能进行开发&#xff0c;…

feign 调用常见问题避坑指南!

摘要&#xff1a;主要是总结了一下这段时间在使用 feign 的过程中的遇到的一些坑点。一、Get请求自动转化成POST的问题1、client 请求参数没有加上 RequestParam 注解问题代码&#xff1a;GetMapping("/showName") String showName(String name);错误提示&#xff1a…

让 APISpace 告诉你什么场景使用什么API

Q1&#xff1a;某商家打算搞年底促销活动&#xff0c;需要将活动信息通过短信的形式通知给用户&#xff0c;这个场景可以用什么接口&#xff1f; 发送通知类的短信&#xff0c;可以使用 通知短信 API~ 通知短信&#xff0c;支持三大运营商&#xff0c;虚拟运营商短信发送&…

第14章 并发控制与恢复

第14章 并发控制与恢复 考试范围&#xff1a; 14.1-14.3, 14.8-14.11 考试题型&#xff1a; 事务操作 考试内容&#xff1a; 1、锁/共享锁/排它锁的概念 2、多粒度锁 Multiple Granularity 3、两阶段封锁协议 The Two-Phase Locking Protocol 两段锁协议是指同一事务对任何…

2.前端笔记-JS-JS3种书写位置、注释、输入输出

书写位置 行内式嵌入式外部文件引入 1、行内式JS 可以将单行或少量的JS代码写在HTML标签的事件属性中&#xff08;以on开头的属性&#xff09;&#xff0c;如onclick单双引号使用&#xff1a;HTML中推荐双引号&#xff0c;JS中推荐单引号&#xff0c;如 <input type&quo…

vue实现将自己网站(h5链接)分享到微信中形成小卡片(超详细)

大家好&#xff0c;我是雄雄。 前言 我们在分享公众号信息到微信或者群中的时候&#xff0c;会出现一个小卡片&#xff0c;如下所示&#xff1a; 但是呢&#xff0c;这种小卡片只能走微信的接口来实现&#xff0c;比如我们从公众号、小程序中分享的内容可以是这样的。如果我们…

0基础转行,四个月,改变了我的人生!

转行对于很多人而言都是一个新的开始&#xff0c;但有的人是决定了立马去做&#xff0c;而有的人则是犹犹豫豫&#xff0c;我考虑考虑吧、还没有决定好、过段时间再说吧…… 就这样&#xff0c;相似情况的两个人&#xff0c;最后有了不同的结果。 很多人总是以我很忙、学历不高…

自学100天,零基础转行软件测试,我要以更好的姿态奔赴下一场山海!

三年大专一场空 专业是电子商务&#xff0c;18年毕业&#xff0c;当时在报考时时觉得电子商务挺高大上的&#xff0c;觉得电商肯定会有前途&#xff0c;以后毕业肯定好找工作&#xff0c;跟大多数人一样&#xff0c;我开始幻想我以后毕业以后的纸醉金迷的生活&#xff0c;我以…

模数转换器ADC

模数转换器ADC F28335内部的ADC模块是一个12位分辨率的、具有流水线结构的模数转换器,其结构框图如图11-1所示。从图11-1可以看到,F28335的ADC模块一共具有16个采样通道,分成了两组,一组为ADCINAO~ ADCINA7,另一组为ADCINBO~ADCINB7。A组的通道使用采样保持器A,也就是图…