跳至主要内容

Python 客户细分入门

在本教程中,您将从零开始学习如何在 Python 中使用 RFM(Recency、Frequency、Monetary)分析实现客户细分。
· 8分钟 阅读

使用 AI 探索

在零售行业,各大连锁大卖场每天都会在各门店产生海量数据。这些数据需要被分析,以便制定更有利润的经营策略。

所有客户的需求各不相同。随着客户群和交易量的增长,想要了解每位客户的具体需求并不容易。识别潜在客户可以提升营销活动效果,最终带动销量增长。细分能够更好地将这些客户分组到不同的细分市场。

什么是客户细分?

客户细分是指根据共同特征将客户划分为群组或簇的方法。 市场研究人员可以在 B2C 模式下,依据客户的人口统计学特征(如职业、性别、年龄、所在地、婚姻状况)、心理特征(如社会阶层、生活方式与个性特征)以及行为特征(如消费、使用习惯、产品/服务使用情况与既往购买产品)来进行细分。在 B2B 模式下,则可依据企业特征,如公司规模、行业类型与所在地等进行细分。

chart

为何需要客户细分

  • 有助于识别最具潜力的客户。
  • 帮助管理者更便捷地与目标受众沟通。
  • 有助于选择与目标细分沟通的最佳媒介。
  • 提升服务质量、忠诚度与留存率。
  • 通过更好地理解各细分需求来改善客户关系。
  • 为向上销售与交叉销售创造机会。
  • 帮助管理者为目标客户设计专属优惠,鼓励其购买更多产品。
  • 助力企业领先竞争对手一步。
  • 帮助识别客户可能感兴趣的新产品。

细分类型

types of segmentation

使用 RFM 分析进行客户细分

RFM(Recency、Frequency、Monetary)分析是一种基于行为的方法,将客户分组。它依据客户以往的购买交易来分组:客户最近一次购买有多近、购买有多频繁、花费了多少钱。RFM 将客户筛选到不同分组,以提供更优服务;帮助管理者识别潜在的高价值客户,从而开展更高利润的业务。有些客户消费金额很高,但如果他们只买过一次,或者很久没买了呢?他们是否经常购买我们的产品?此外,它还帮助管理者开展更有效的个性化促销活动。

  • Recency(R,最近一次):谁是最近发生购买的?即距上次购买的天数(越小越好)。
  • Frequency(F,频率):谁购买得更频繁?即购买次数总计(越高越好)。
  • Monetary Value(M,金额):谁的购买金额更高?即客户累计花费的总金额(越高越好)。

此处,三个变量(Recency、Frequency、Monetary)各分为四个等分组,由此可产生 64(4x4x4)个不同的客户细分。

RFM(Recency、Frequency、Monetary)步骤:

  1. 为每位客户计算 Recency、Frequency、Monetary 值。
  2. 使用四分位数为 RFM 表添加分箱值。
  3. 将客户的 RFM 评分按升序排序。

1. 为每位客户计算 Recency、Frequency、Monetary 值。

Recency, Frequency, Monetary values

2. 使用四分位数为 RFM 表添加分箱值。

segment bin values on RFM table

3. 将所有分数合并到单列(RFM_Score)。

all scores in single column

使用 Python 通过 RFM 识别潜在客户细分

导入所需库

#import modules
import pandas as pd # for dataframes
import matplotlib.pyplot as plt # for plotting graphs
import seaborn as sns # for plotting graphs
import datetime as dt

加载数据集

首先使用 pandas 的 read CSV 函数加载所需的 HR 数据集。您可以通过此链接下载数据。

data = pd.read_excel("Online_Retail.xlsx")
data.head()
dataset 1
data.tail()
dataset 2
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 541909 entries, 0 to 541908
Data columns (total 8 columns):
InvoiceNo      541909 non-null object
StockCode      541909 non-null object
Description    540455 non-null object
Quantity       541909 non-null int64
InvoiceDate    541909 non-null datetime64[ns]
UnitPrice      541909 non-null float64
CustomerID     406829 non-null float64
Country        541909 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 33.1+ MB
data= data[pd.notnull(data['CustomerID'])]

去重

有时您会拿到比较“脏”的数据集,需要处理重复值,否则会导致分析偏差。在Python中,pandas 提供了 drop_duplicates() 函数,用于删除重复记录。

filtered_data=data[['Country','CustomerID']].drop_duplicates()

开始挖掘数据洞察

#Top ten country's customer
filtered_data.Country.value_counts()[:10].plot(kind='bar')
<matplotlib.axes._subplots.AxesSubplot at 0x7fd81725dfd0>
data insights

在本数据集中,您会发现大多数客户来自“United Kingdom”。因此,您可以筛选出英国客户的数据。

uk_data=data[data.Country=='United Kingdom']
uk_data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 361878 entries, 0 to 541893
Data columns (total 8 columns):
InvoiceNo      361878 non-null object
StockCode      361878 non-null object
Description    361878 non-null object
Quantity       361878 non-null int64
InvoiceDate    361878 non-null datetime64[ns]
UnitPrice      361878 non-null float64
CustomerID     361878 non-null float64
Country        361878 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 24.8+ MB

pandas 中的 describe() 函数可便捷地获取各类汇总统计。该函数返回计数、均值、标准差、最小值、最大值以及分位数等信息。

uk_data.describe()
 QuantityUnitPriceCustomerID
count361878.000000361878.000000361878.000000
mean11.0770293.25600715547.871368
std263.12926670.6547311594.402590
min-80995.0000000.00000012346.000000
25%2.0000001.25000014194.000000
50%4.0000001.95000015514.000000
75%12.0000003.75000016931.000000
max80995.00000038970.00000018287.000000

这里可以看到,部分客户的订购数量为负值,这是不可能的。因此需要筛选出 Quantity 大于 0 的记录。

uk_data = uk_data[(uk_data['Quantity']>0)]
In: # Change the name of columns
rfm.columns=['monetary','frequency','recency']
uk_data.info() 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 354345 entries, 0 to 541893
Data columns (total 8 columns):
InvoiceNo      354345 non-null object
StockCode      354345 non-null object
Description    354345 non-null object
Quantity       354345 non-null int64
InvoiceDate    354345 non-null datetime64[ns]
UnitPrice      354345 non-null float64
CustomerID     354345 non-null float64
Country        354345 non-null object
dtypes: datetime64[ns](1), float64(2), int64(1), object(4)
memory usage: 24.3+ MB

筛选所需列

此处筛选进行 RFM 分析所需的必要列。您只需要五列:CustomerID、InvoiceDate、InvoiceNo、Quantity 和 UnitPrice。CustomerID 唯一标识客户;InvoiceDate 用于计算最近一次购买时间;InvoiceNo 用于统计交易发生的次数(频率);每次交易的 Quantity 及每个单位的 UnitPrice 将帮助您计算总购买金额。

uk_data=uk_data[['CustomerID','InvoiceDate','InvoiceNo','Quantity','UnitPrice']]
uk_data['TotalPrice'] = uk_data['Quantity'] * uk_data['UnitPrice']
uk_data['InvoiceDate'].min(),uk_data['InvoiceDate'].max()
(Timestamp('2010-12-01 08:26:00'), Timestamp('2011-12-09 12:49:00'))
PRESENT = dt.datetime(2011,12,10)
uk_data['InvoiceDate'] = pd.to_datetime(uk_data['InvoiceDate'])
uk_data.head()
 CustomerIDInvoiceDateInvoiceNoQuantityUnitPriceTotalPrice
017850.02010-12-01 08:26:0053636562.5515.30
117850.02010-12-01 08:26:0053636563.3920.34
217850.02010-12-01 08:26:0053636582.7522.00
317850.02010-12-01 08:26:0053636563.3920.34
417850.02010-12-01 08:26:0053636563.3920.34

RFM 分析

这里将执行以下操作:

  • Recency:计算当前日期与每位客户最后一次购买日期之间的天数。
  • Frequency:计算每位客户的订单数。
  • Monetary:计算每位客户的购买金额总和。
rfm= uk_data.groupby('CustomerID').agg({'InvoiceDate': lambda date: (PRESENT - date.max()).days,
                                        'InvoiceNo': lambda num: len(num),
                                        'TotalPrice': lambda price: price.sum()})
rfm.columns
Index(['InvoiceDate', 'TotalPrice', 'InvoiceNo'], dtype='object')
# Change the name of columns rfm.columns=['recency', 'monetary', 'frequency'] 
rfm['recency'] = rfm['recency'].astype(int)
rfm.head()
 monetaryfrequencyrecency
CustomerID   
12346.032577183.601
12747.024196.01103
12748.0033719.734596
12749.034090.88199
12820.03942.3459

计算 RFM 值的分位数

最近一次消费最短、购买频率与消费金额最高的客户,被视为顶级客户。

qcut() 是基于分位数的离散化函数,会根据样本分位数对数据进行分箱。例如,对 1000 个值按 4 个分位切分,将生成一个表示每位客户所处分位箱的分类对象。

rfm['r_quartile'] = pd.qcut(rfm['recency'], 4, ['1','2','3','4'])
rfm['f_quartile'] = pd.qcut(rfm['frequency'], 4, ['4','3','2','1'])
rfm['m_quartile'] = pd.qcut(rfm['monetary'], 4, ['4','3','2','1'])
rfm.head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartile
CustomerID      
12346.032577183.601111
12747.024196.01103414
12748.0033719.734596414
12749.034090.88199414
12820.03942.3459324

RFM 结果解读

将三个四分位标签(r_quartile、f_quartile、m_quartile)合并为单列,该排序将帮助您更好地细分客户群。

rfm['RFM_Score'] = rfm.r_quartile.astype(str)+ rfm.f_quartile.astype(str) + rfm.m_quartile.astype(str)
rfm.head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartileRFM_Score
CustomerID       
12346.032577183.601111111
12747.024196.01103414414
12748.0033719.734596414414
12749.034090.88199414414
12820.03942.3459324324
# Filter out Top/Best cusotmers
rfm[rfm['RFM_Score']=='111'].sort_values('monetary', ascending=False).head()
 monetaryfrequencyrecencyr_quartilef_quartilem_quartileRFM_Score
CustomerID       
16754.03722002.42111111
12346.032577183.61111111
15749.023544534.310111111
16698.02261998.05111111
13135.01963096.01111111

结论

恭喜您读完本教程!

在本教程中,您学习了大量关于客户细分的内容:什么是客户细分、为何需要客户细分、细分类型、RFM 分析,以及如何在 Python 中从零实现 RFM。同时还涉及了一些 pandas 的基础概念,如处理重复值、groupby 与基于样本分位的 qcut() 分箱。

希望您现在能够将主题建模应用到自己的数据集中。感谢阅读本教程!

如果您想进一步学习 Python,欢迎参加 DataCamp 的免费课程 Intro to Python for Data Science。

主题