第10章 用户分层实战

10.1 用户分层的基本概念

无处不在的用户分层

用户分层,顾名思义,是把用户按照一定的规则划分成不同的层级,如图 10- 1 所示。


图 10-1 用户分层示例

想玩游戏了,打开《王者荣耀》,看到新出的英雄皮肤效果炫酷,忍不住充值购买,系统提示我的 VIP 等级提升了,从 V 6 升级到尊贵的 V 7。不过,之后因为我一段时间没有消费,等级又退回到了 V 6。

想买双鞋了,找到某品牌天猫旗舰店,轻车熟路地点开店铺会员中心,因为我已经是铂金等级的会员,每月能领取一张满 500- 50 的优惠券。再消费 3000 元,就能升级到最高级别的至尊会员,还可以享受每季度的线下 VIP 活动。

想喝咖啡了,在星巴克小程序上下单,发现了醒目的会员等级提示和不同等级权益的详细说明。星巴克目前的会员分成 3 个等级,从低到高分别是银享级、玉享级和金享级。要想提升会员等级,就需要攒到一定数量的星星。例如从银享级升级到玉享级,需要 4 颗星,而每消费 50 元可以获得一颗星,这意味着需要消费满 200 元。

生活中,用户分层可谓无处不在。

用户分层的类型

用户分层可以分为两种类型——外向型和内向型,如图 10- 2 所示。


图 10-2 两种用户分层类型

外向型分层指品牌基于数据分析确定用户分层之后,将其作为标准向外宣传展示。常见的做法是直接按照用户分层的标准构建会员体系,并在醒目的资源位展示宣传,作为品牌整体用户战略的重要部分,一旦确定,绝不轻易变更。

内向型分层则是品牌用户运营相关的部门为了更好地达成 KPI,通过对用户分层进行精细化运营。这种分层一般更加细致和灵活,可以随运营目标而调整。不过,内向型分层并不会对外展示,只是用户运营的辅助工具。

本章将主要围绕对品牌影响更深远的外向型分层展开。

用户分层的特征

本章开头的 3 个例子中,平台和品牌根据消费金额把用户分成了不同的级别,这些级别之间有着显著的等级关系、明确的晋升路径、差异化的奖励机制,这也是用户分层的 3 个典型特征。

口显著的等级关系:在用户分层体系中,各层之间的等级秩序非常明显。虽然不同分层可能使用不同的命名方式,但消费者几乎可以立即识别出等级的高低,例如,VIP 8 高于 VIP 2,黄金会员高于白银会员。

口明确的晋升路径:当用户满足一定条件时,便可以从低等级晋升至高等级。这些条件通常与交易相关,可以通过具体的数值进行量化。

口差异化的奖励机制:根据用户等级的不同,平台和品牌为用户提供了不同力度的权益。用户的等级越高,为其提供的实惠和特权就越多。这种差异化的奖励机制能激励用户提高消费水平,从而增强其对平台和品牌的黏性。奖励可能包括折扣、优惠券、专属客服、活动预览等。

为什么要做用户分层

很多人把做用户分层的原因归结为精细化运营的需要,有一定道理,但这只是冰山一角,要搞清楚为什么品牌都喜欢做用户分层,我们还需要看得更深一些。

1. 供需关系的转变

在一个供不应求的市场里,品牌最关注的两件事是定价和产能。在条件允许的情况下能把价格提升多少?如何开足马力、加大产能以生产更多的产品?至于怎样维护好和用户的关系,怎样用科学的方法对用户进行分层,对品牌来说,既无必要也没兴趣。

反之,在供过于求的市场里,市场上有各种品牌的产品相互竞争,产品同质化严重,选择权牢牢掌握在用户的手中。这个时候,品牌则需要通过维护好和用户的关系,用各种奖励忠诚的方式来增强自己的竞争力。现如今大多数行业都处于这种供求状态,因此大家会发现几乎所有的品牌都在做用户分层,并基于分层搭建自己的会员体系。

2. 资源的有限性

品牌的资源都是有限的,如果将资源和福利无差别地投到每个用户身上,会带来两个问题:其一,会引来巨量的羊毛党,无底线地薅羊毛任何品牌都无法承受;其二,忠诚的用户并未受到特殊的关注,他们很可能转而投向对忠诚用户特殊关照的品牌。因此,在资源有限的情况下,品牌必须筛选出不同等级的用户,差异化投入和运营,以期达到每层用户的最佳 ROI。

3. 提升用户忠诚度

用户分层,除了把用户分为不同的等级,为每个等级设置针对性的激励策略也同样重要。通过给予高等级用户丰富的特权和激励,可以有效维护高等级用户的忠诚度;同时,对低等级用户来说,高等级的丰厚激励会吸引和促使他们不断完成品牌期待的关键动作(如持续消费),以实现等级的提升。

分层的两个问题

要进行用户分层,首先要解决的两个问题便是“根据什么指标来分”和“分多少层”。

1. 根据什么指标来分

本章开头的 3 个例子,无论对于《王者荣耀》、某品牌天猫店还是星巴克,营收都是最核心的指标,因此,它们都按照用户的累计消费金额来区分等级。我们期望用户完成什么关键行为,就可以用这种行为的数据来划分用户等级。对于平台和品牌来说,用户的活跃指标虽然重要,但远远比不上真金白银的消费。所以,用累计消费金额来划分用户等级,是目前最常用的一种方式。

2. 分多少层

由于平台和品牌有较大的差异性,这里我们主要从品牌的视角来思考“用户应该分多少层”这个问题。

口分层太少(如分 2 层),难以体现不同等级的差异化激励。如果门槛标准设置太低,用户很容易达到最高等级,有一种“轻轻一跃便上山巅"的感觉,大概率是不会珍惜眼前的美景——高等级激励的;如果门槛标准设置太高,低等级用户会有“难于上青天"之感。

口分层过多(超过 5 层),容易让用户信息过载,导致大部分用户无法记住甚至没有兴趣看不同等级所对应的福利,更谈不上这些福利最终对用户的关键行为有多少实际的激励作用。

所以,大部分品牌用户分层的数量在 3~5 层之间。最低等级几乎没有限制门槛,目的是吸引用户绑定,品牌可以获取用户关键信息并引导用户初次体验产品;中间等级则可以筛掉一些羊毛的用户,通过一些日常的奖励,促使用户持续留存和购买;高等级用户是品牌最核心的人群,需要给予最大的资源投入与最好的福利,维持核心用户的忠诚,并吸引其他等级的用户向上升级。

下面,我将给大家提供实际的案例数据,在介绍几种用户分层方法的同时带大家用 Pandas 实操。

10.2 二八法则

二八法则在用户分层上的应用

二八法则过于经典,相信不少读者耳朵都听出茧子了。二八法则应用到电商场景下,可以概括为“20%的用户贡献了 80%的销售额”,这 20%用户是品牌最核心的用户,如图 10- 3 所示。当然,法则中的 20%和 80%两个数字,在实际中会有所波动,但总体都符合少量核心用户做出大量贡献的规律。

怎么将二八法则与用户分层相结合呢?很简单,根据二八法则直接切分就好。这里我们以把用户分 3 层为例。先按照用户的累计支付金额降序排列,找到前 20%的用户。如此一来,整体用户被分成了前 20%和后 80%两个人群。

然后,在前 20%的用户中,继续按照二八法则切分,最高等级的人群占比为 4%(20%×20%)。最终,整体用户被分成了低、中、高三个等级,对应的人数占比分别是 80%、16%、4%。


图 10-3 二八法则

百说不如一练,我们用 Pandas 来实践一下。

数据预览

1. 数据扫描

首先,导入我们的案例数据,数据是阿粥(小 z)品牌下的店铺 2023 年 1~12 月的订单数据:

df = pd. read_excel ('主订单数据集. xlsx') df.head ()

前几行结果如下:

品牌名店铺名称主订单编号用户 ID付款时间订单状态实付金额购买数量
0阿粥(小 z)数据不吹牛73465136654uid 1354603662023-01-0109:32:12交易成功166
1阿粥(小 z)数据不吹牛73465136655uid 1354603672023-01-0109:11:50交易成功117
2阿粥(小 z)数据不吹牛73465136656uid 1354603682023-01-0111:49:02交易成功166
3阿粥(小 z)数据不吹牛73465136657uid 1354603692023-01-0112:20:24交易成功77
4阿粥(小 z)数据不吹牛73465136658uid 1354603702023-01-0101:23:15交易成功158

获取数据的关键信息,对数据进行快速扫描:

print (df.info ()) print (df.describe ())

运行结果如下:

df.info () <class 'pandas.core.frame.DataFrame'> RangeIndex: 356233 entries, 0 to 356232 Data columns (total 8 columns): # Column Non- Null Count dtype 0 品牌名 356233 non- null object 1 店铺名称 356233 non- null object

2 主订单编号 356233 non- null int 64 3 用户 ID 356231 non- null object 4 付款时间 356233 non- null object 5 订单状态 356233 non- null object 6 实付金额 356233 non- null int 64 7 购买数量 356233 non- null int 64 dtypes: int 64 (3), object (5) memory usage: 21.7+ MB

df.describe () 主订单编号实付金额购买数量 count 3.562330 e+05 356233.000000 356233.000000 mean 7.346531 e+10 166.493065 1.116438 std 1.028358 e+05 153.645028 0.817845 min 7.346514 e+10 40.000000 1.000000 25% 7.346523 e+10 77.000000 1.000000 50% 7.346531 e+10 146.000000 1.000000 75% 7.346540 e+10 203.000000 1.000000 max 7.346549 e+10 29309.000000 150.000000

通过 Pandas 快速扫描,数据的关键信息已经明确,具体如下。

口数据集一共 35.6 万行,包含品牌名、店铺名称、主订单编号、用户 ID、付款时间、订单状态、实付金额和购买数量的字段。需要注意的是,实付金额是这条交易记录的总金额,不用再乘以购买数量。

口 df. info()的结果显示,只有用户 ID 有两个缺失值,整体数据还算完整。

口 df. describe()把主订单编号当作数值来统计,直接忽略即可。但我们可以明显发现这份数据中的实付金额和购买数量存在异常值,单条记录的最高金额接近 3 万元,购买数量也达到了令人难以置信的 150。

2. 主订单和子订单的区别

一般订单数据会分为主订单和子订单两种类型,以上是一份很典型的主订单数据集。主订单和子订单的差异如图 10- 4 所示。


图 10-4 主订单和子订单的差异

主订单会把用户同一时间下单的商品聚合,汇总成一条数据;而子订单则对应到一个个具体的商品。例如某用户的购物车中有 2 件不同的商品,同一时间付了款,主订单只有 1 行记录,而子订单会有 2 行。

数据清洗

1. 用户 ID 缺失值处理

用户 ID 只有极少量的缺失值,直接将相关行删掉即可:

df = df. loc[df['用户 ID']. isnull () == False, :] print (df.info ())

运行结果如下:

<class 'pandas.core.frame.DataFrame'>Int64Index: 356231 entries, 0 to 356232Data columns (total 8 columns):    # Column Non- Null Count dtype    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 品牌名 356231 non- null object    1 店铺名称 356231 non- null object    2 主订单编号 356231 non- null int64    3 用户 ID 356231 non- null object    4 付款时间 356231 non- null object    5 订单状态 356231 non- null object    6 实付金额 356231 non- null int64    7 购买数量 356231 non- null int64    dtypes: int64(3), object(5)    memory usage: 24.5+ MB

2. 异常值处理

四分位法是处理异常值时常用的方法,其原理如图 10- 5 所示。


图 10-5 四分位法原理

从统计的角度看,数据从小到大排序后,下四分位数 Q1 、中位数 Q2 、上四分位数 Q3 把整个数据切分成了 4 段,每一段都包含 25% 的值。对应到箱线图,如果数值高于箱线图的上限或者低于箱线图的下限,则将其判定为异常值。

上限和下限主要用 Q1Q3 来计算:

上限 τ=Q3+n ( Q3Q1 一下限 τ=Q1n ( Q3Q1

其中 Q3Q1 常叫作四分位距(简称 IQR),是度量数据离散程度的有效参数。这里的 n 可以根据实际情况灵活设置, n 越大,对于异常值越包容。一般认为:当 n=1.5 时,能够剔除基础的异常值;当 n3 时,剔除的是极端的异常值。

因为订单数据涉及大促活动,难免有用户极端的囤货行为,这里我们用 n=3 作为异常值剔除的标准。

先计算上限和下限的值:

up df. describe()['实付金额']['75%'] + (df. describe()[实付金额']['75%']- df. describe()[实付金额']['25%'])*3 low df. describe()[实付金额']['25%']- (df. describe()[实付金额']['75%']- df. describe()[实付金额']['25%'])*3 print(实付金额的上限值:,up)print(实付金额的下限值:,low)

分位数直接取材于 df. describe()的统计结果,计算得到了上下限:

实付金额的上限值:581.0 实付金额的下限值:- 301.0

订单金额下限不可能为负,因此只需对上限值进行异常值剔除处理:

df = df. loc[df['实付金额'] <= up,:] df.describe ()

所有超过 581 元的订单均被剔除,结果如下:

主订单编号实付金额购买数量
count 3.533680 e+05353368.000000353368.000000
mean 7.346531 e+10160.6091501.103861
std 1.027865 e+0599.0924190.645977
min 7.346514 e+1040.0000001.000000
25% 7.346523 e+1077.0000001.000000
50% 7.346531 e+10146.0000001.000000
75% 7.346540 e+10199.0000001.000000
max 7.346549 e+10581.000000145.000000

一波刚平,一波又起。金额正常了,但购买数量最大值还是 145,有的读者可能会疑惑:“刚才剔除金额的时候为什么不一起把购买数量剔掉?”

那是因为绝大部分用户的购买数量是 1,最开始 describe()中的上下四分位数也都是 1,相减之后是 0,没有任何意义。我们使用购买数量对应的订单数分布来筛选:

统计不同购买数量对应的订单数分布 ct_count = df['购买数量']. value_counts (). reset_index () ct_count. columns = ['购买数量', '订单数'] #统计订单数占比ct_count ['订单数占比'] = ct_count['订单数'] / ct_count['订单数']. sum () #订单数占比累加结果ct_count ['累计订单数占比'] = ct_count['订单数占比']. cumsum () ct_count.head (10) 运行结果如下:

运行结果如下:

购买数量订单数订单数占比累计订单数占比
0 13297390.9331320.933132
1 2142160.0402300.973362
2 379980.0226340.995996
3 46870.0019440.997940
4 54490.0012710.999210
5 61520.0004300.999641
6 7350.0000990.999740
7 10260.0000740.999813
8 8120.0000340.999847
9 9110.0000310.999878

绝大部分订单的购买数量是 1,购买数量小于或等于 5 的订单占总订单的比重高达 99.92% ,接近全部了。这里以 5 作为标准,保留购买数量小于或等于 5 的数据:

df = df. loc[df['购买数量'] <= 5,:]

3. 订单状态筛选

订单相关的数据如果有订单状态的字段,一定要留意。我们来观察一下目前的订单状态分布:

df['订单状态']. value_counts ()

运行结果如下:

交易成功 289386 付款以前,卖家或买家主动关闭交易 37242 付款以后用户退款成功,交易自动关闭 26447 等待买家确认收货,即卖家已发货 14 Name: 订单状态, dtype: int 64

订单状态差异是造成口径差异的一个重要因素,这里我们只保留成功的订单:

df = df. loc[df['订单状态'] == '交易成功',:] print ('清洗之后的订单量: ', len (df))

清洗之后的订单量为 289386。终于把手洗干净,可以开动吃正餐了。

二八法则下的用户分层

如果要根据二八法则把用户分为三层,需要切两刀:第一刀划出前 20% 和后 80% ,第二刀再从前 20% 里切出前 20% (全部用户的前 4% )。也就是说,我们根据实付金额将用户降序排列,再统计前 4% 、前 20% 对应的金额就可以了。

第一步,先根据实付金额将用户降序排列:

每个用户金额汇总 group_28=df. groupby(用户 ID)[实付金额). sum(). sort_values(ascending False). reset_index () #增加 “用户序号”列用于后续筛选,序号从 1 开始 group_28[用户序号 list(range(1, len(group_28)+1)) group_28. head ()

按用户 ID 分组,统计每个用户的实付金额并按降序排列,结果如下:

用户 ID 实付金额用户序号 0 uid 135476531 39758 11 uid 135460679 35543 22 uid 135467627 30916 33 uid 135473980 23619 44 uid 135465649 21015 5

第二步,确定前 4% 、前 20% 的用户对应的位置:

top_4 = round (len (group_28) * 0.04) top_20 = round (len (group_28) * 0.20) print ('前 4%对应的最后一个序号:', top_4) print ('前 20%对应的最后一个序号:', top_20)

这里直接用总用户数乘以对应的分位数,再用 round()方法截取整数位,得到对应的用户序号:

前 4%对应的最后一个序号:5420 前 20%对应的最后一个序号:27101

第三步,根据序号筛选出对应的分层金额门槛:

print('前 4%对应的金额门槛:',group_28. loc{group_28['用户序号'] == top_4,实付金额). values) print('前 20%对应的金额门槛:',group_28. loc{group_28['用户序号'] == top_20,实付金额j.values)

在按金额排序的用户分组中,运行上述代码找到对应的金额门槛:

前 4%对应的金额门槛:[1037]前 20%对应的金额门槛:[460]

根据金额门槛我们对用户进行分层打标,其中消费金额小于 460 元的为低级用户,大于或等于 460 元且小于 1037 元的为中级用户,大于或等于 1037 元的是高级用户。通过自定义函数和 apply()方法来实现:

根据金额打标

def judge (x): if x>=1037 . return,高级用户, elif x>=460 . return,中级用户, else: return,低级用户,

group_28['用户等级'] = group_28['实付金额']. apply (judge) group_28. head ()

运行结果如下:

用户 ID实付金额用户序号用户等级
0uid 135476531397581高级用户
1uid 135460679355432高级用户
2uid 135467627309163高级用户
3uid 135473980236194高级用户
4uid 135465649210155高级用户

二八法则的用户分层到此已经完成,最后我们统计不同等级的会员金额占比:

直接根据等级标签做金额汇总 group_28_rank = group_28. groupby ('用户等级')['实付金额']. sum (). reset_index () 计算不同等级会员的金额占比 group_28_rank['金额占比'] = group_28_rank['实付金额'] / group_28_rank['实付金额']. sum () group_28_rank. sort_values (['实付金额']) 运行代码得到了高级、中级、低级用户金额及占比:

运行代码得到了高级、中级、低级用户金额及占比:

用户等级实付金额金额占比 2 高级用户 9087072 0.1997170 中级用户 14104956 0.3100001 低级用户 22307802 0.490283

4% 的用户(高级用户)贡献了总金额的 20% 左右,由中级和高级用户构成的前 20% 用户贡献了总金额的 50% 左右,符合“较少量用户贡献较大量金额”的逻辑,不过结果并不像二八法则中 20% 贡献 80% 那么突出。

10.3 拐点法

不同于二八法则分层的简单粗暴,拐点法依托于数据分布中的关键转折点,为用户分层提供了更加科学且合理的依据。

什么是拐点法

拐点,在一些地方也叫作魔法数字,它广泛应用于数据分析之中,用于指导运营和决策。例如:口某社交软件发现,如果新注册的用户在 7 天内关注了 20 个以上的用户,那么他的留存概率会大幅提升;口某电商品牌发现,如果用户累计消费超过 300 元,那么其用户生命周期会显著延长。这里的关注 20 个用户、累计消费 300 元即魔法数字,从数据趋势上看就是拐点,如图 10- 6 所示。


新用户关注人数与次月留存率的关系图 10-6 趋势图拐点

当用户的某个动作达到了拐点的标准时,其关键行为(如留存)较之前会有显著提升,而拐点法就是通过观察数据趋势,找到这些关键的拐点。

拐点法在用户分层上的应用

拐点法的核心在于两个指标的选择。

第一个指标:衡量用户的某个行为,例如 7 天内关注了 20 个以上的用户;用户累计消费超过 300 元。这个指标必须是品牌有能力去影响的指标,否则就算找到拐点,品牌无能为力,也于事无补。

第二个指标:指的是品牌希望提升什么指标,如次月留存率、用户生命周期价值。这个指标通常是品牌希望实现的关键目标,带有一定的预期性。

对应到用户分层上,为了让大家更好地理解,我们先来思考第二个指标:为什么要做用户分层?我们想通过用户分层提升什么?

“通过分层来提升用户长期忠诚度”是分层的核心目的之一。那么忠诚度又应该通过什么指标来量化呢?复购率是一个不错的答案,因为只有对品牌忠诚的用户才会重复购买。

我们希望提升用户的复购率,同时会用消费金额来对用户进行分层。两者结合,我们可以把用户的消费金额作为第一个指标,观察不同消费区间的用户对应留存率的变化趋势,从而找到消费金额与留存率之间的关系,并尝试找到关键的拐点,作为用户分层的参考值。

两个指标已经确定了,但是复购率怎么计算才合理呢?

基于 Pandas 的拐点法分层

1. 数据回顾

经过之前的数据清洗和分析,我们可以直接拿到 2023 年每个用户的消费金额汇总表 group_28:

用户 ID实付金额用户序号用户等级
0uid 135476531397581高级用户
1uid 135460679355432高级用户
2uid 135467627309163高级用户
3uid 135473980236194高级用户
4uid 135465649210155高级用户

我们将其重新命名,并把之前二八法则确定的用户等级删掉,只保留了用户 ID 和实付金额:

group_kneed = group_28. iloc[:,: 2] group_kneed.head ()

运行结果如下:

用户 ID实付金额
0uid 13547653139758
1uid 13546067935543
2uid 13546762730916
3uid 13547398023619
4uid 13546564921015

2. 关键指标口径确认

我们已经得到了拐点法的第一个指标——用户实付金额,第二个指标复购率该如何计算呢?

由于这里的复购率是衡量用户忠诚度的,带有预期的性质,所以我们采用隔断复购率的计算逻辑,如图 10- 7 所示。


图 10-7 隔断复购率的计算逻辑

品牌整体的订单被隔断,分为 A 和 B 两个时间段。

A 时间段范围较大,以保证用户数据足够稳定,我们计算该时间段每个用户的消费金额。

B 时间段又叫复购观察期,时间跨度根据品牌用户和产品的特性来确定,一般是 3 个月以上,即用户 3 个月以上不购买,那么他流失或不忠诚的概率就非常大。

通过分析 A 时间段不同消费区间的用户在 B 时间段是否购买(见图 10- 8),得到 A 时间段不同消费区间的隔断复购率趋势,帮助寻找消费区间和复购率的拐点。


图 10-8 复购判断细化

在本章的案例中,假设当前时间是 2024 年 4 月 1 日,为了分析方便,可以把 A 时间段设定为 2023 年 1~12 月(实际分析中建议将这个时间拉得更长,以保证数据足够稳定),也就是之前处理的那部

分数据,把 B 时间段定为 2024 年 13 月,即最近 3 个月。厘清了指标逻辑,我们继续用 Pandas 分析。

3. 不同消费区间的打标

最终分析的是不同消费区间和复购率变化趋势。首先需要按消费区间对不同用户进行打标,这里我们以 100 元为一个区间划分。先准备区间数据:

将分组金额按 100 元一个区间切分,直到 1500 元,再往上用一个极大值封顶 bins = list (range (0, 1600, 100)) + [1000000]

构造分组标签 ranges = []

最终把分组标签构造成 0- 100,100- 200,200- 300, for start, end in zip (range (0,1500,100), range (100,1600,100)): interval = str (start) + - +str (end) ranges.append (interval) ranges.append ('1500+') print('分组区间:', bins) print('分组区间对应的标签:', ranges)

以上代码分别构造了分组区间和分组区间对应的标签,具体如下。(这为接下来的切分做好了准备。)

分组区间:[0,100,200,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1000000]分组区间对应的标签:[0- 100,'100- 200','200- 300','300- 400','400- 500','500- 600','600- 700','700- 800','800- 900','900- 1000','1000- 1100','1100- 1200','1200- 1300','1300- 1400','1400- 1500','1500+']

有了对应的区间之后,打标直接用 pd. cut()方法:

group_kneed['消费区间'] = pd.cut (group_kneed['实时金额'], bins = bins, labels = ranges) group_kneed

把每个用户的实付金额按对应区间打标,得到如下结果:

用户 ID实付金额消费区间
0uid 135476531397581500+
1uid 135460679355431500+
2uid 135467627309161500+
3uid 135473980236191500+
4uid 135465649210151500+
............
135499uid 135551937400~100
135500uid 135583969400~100
135501uid 135493631400~100
135502uid 135486524400~100
135503uid 135610430400~100
135504rows × 3 columns

消费区间划分完成,该进行不同区间复购率的计算了。

4. 不同区间复购率的计算

筛选出 2024 年 13 月的订单,然后用 2023 年的用户和它匹配,匹配上的用户即复购用户,再计算这部分用户的占比就能得到复购率。

在这一步,我已经为大家准备好了在 2024 年 13 月复购用户的 ID,省去了匹配筛选环节。

repur = pd. read_excel ('2024 年 1~3 月复购用户. xlsx') repur.head ()

repur 记录了复购用户的 ID:

用户 ID 0 uid 135477653 1 uid 135521126 2 uid 135542845 3 uid 135531153 4 uid 135518141

拿到这份 ID,可以判断用户是否复购:

group_kneed['是否复购'] = group_kneed['用户 ID']. isin (repur['用户 ID']) group_kneed.head ()

以上代码判断每个用户是否在 2024 年 13 月复购打标完成,运行结果如下:

用户 ID 实付金额消费区间是否复购 0 uid 135476531 39758 1500+ True 1 uid 135460679 35543 1500+ True 2 uid 135467627 30916 1500+ False 3 uid 135473980 23619 1500+ alse 4 uid 135465649 21015 1500+ False

下一步,计算每个区间的用户数,作为复购率计算的分母:

group_kneed_inter = group_kneed.groupby ('消费区间')['用户 ID']. count () .reset_index () group_kneed_inter. columns = ['消费区间','用户数'] group_kneed_inter.head ()

运行结果如下:

消费区间用户数
00~10021033
1100~20040013
2200~30023074
3300~40017995
4400~50010036

接着,计算每个区间的复购人数:

group_if_repur = group_kneed.groupby ('消费区间')['是否复购']. sum (). reset_index () group_if_repur. columns = ['消费区间','复购人数'] group_if_repur.head ()

依然按照消费区间分组,对“是否复购”列进行汇总,得到复购人数的统计结果:

消费区间复购人数
00~100
1100~200
2200~300
3300~400
4400~500

之前的“是否复购”列由 True 和 False 布尔值构成,为什么用 sum()方法进行汇总之后,却得到了复购人数呢?这是因为在参与计算时,True、False 分别对应数值 1 和 0。也就是说,我们对复购人数做了汇总。

有了消费区间、用户数、复购人数三列,复购率的计算呼之欲出:

group_kneed_result = pd.merge (group_kneed_inter, group_if_repur, left_on = '消费区间', right_on = '消费区间', how = 'inner') group_kneed_result['复购率'] = group_kneed_result['复购人数'] / group_kneed_result['用户数'] group_kneed_result.head ()

根据消费区间把用户数和复购人数合并,同时用复购人数除以用户数,得到复购率:

消费区间用户数复购人数复购率
0 0~1002103315350.072981
1 100~2004001351620.129008
2 200~3002307439000.169021
3 300~4001799535450.196999
4 400~5001003620170.200976

5. 结果可视化与分析

关键指标均已计算完成,最后绘制消费区间和复购率趋势图:

导入必要的富图库并做设置,此处省略#...

fig = plt.figure (figsize = (8,4))

绘制折线图

plt.plot (group_kneed_result['消费区间'], group_kneed_result['复购率']) * 100, marker='o', color = 'r', alpha = 0.7)

设置图表标题和坐标轴标签

plt.title ('用户消费区间与复购率趋势图') plt.xlabel ('消费区间/元') plt.ylabel ('复购率/元') #旋转标题避免文字重叠

plt.xtickss (rotation=45)

绘制网格线

plt.grid (True, linestyle=- - - ', alpha=0.7)

运行结果如图 10- 9 所示。


图 10-9 用户消费区间与复购率趋势

从用户消费区间与留存率趋势图可以清楚地看到以下消息。

口 400 元以内,用户每多消费 100 元,其留存率都会有显著的提升;当消费 0100 元时,用户的留存率为 7.5% ;当消费达到 300400 元时,用户的留存率提升到近 20% ;其后一段区间趋于稳定。因此,第一个拐点是 300400 元的消费区间。

口消费区间 800900 元是另一个提升的拐点,该区间较之前的留存率提升明显,且 800900 元之后的消费区间留存率虽有增长,但已相对缓慢。

结合数据观察,我们从趋势图中发现了两个具有拐点性质的消费区间。消费区间的数据可以拆得更细,进行更精准的金额定位,总体逻辑是完全一样的。

基于运营策略“稳定起见”的原则:消费 400 元的人数比消费 300 元的要少,分层激励投入的资源相对较少,而且消费 400 元的用户大概率要比消费 300 元的留存率更高,这符合资源投入少、用户质量高的特点。因此结合业务视角,以两个拐点消费区间的上界作为用户分层的标准:

口消费低于 400 元的用户为低等级用户,品牌应该通过优惠等激励,促进早期用户更多消费以提升其复购率。

口消费大于或等于 400 元且小于 900 元的用户为中级用户。这部分用户的忠诚度已经有所提升,但应该进一步促进其消费,让他们与品牌建立更深层的关系。

口消费大于或等于 900 元的用户则为高级用户,是品牌最核心和忠诚的用户,无论是新品尝试还是营销活动传播,他们都是最有动力的一群人,品牌必须足够重视他们并给予关怀奖励。

利用拐点法进行用户分层至此已经全部完成。

10.4 本章小结

在本章中,我们先学习了用户分层的基本概念,包括用户分层有哪些类型,为什么要做用户分层以及怎么样做。在此基础上,我们结合实际的案例数据,用 Pandas 先清洗、后分析。