前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「Python」用户消费行为分析

「Python」用户消费行为分析

作者头像
曼亚灿
发布2023-05-17 21:44:07
9410
发布2023-05-17 21:44:07
举报
文章被收录于专栏:亚灿网志亚灿网志

一个数据分析案例

请注意,本文编写于 297 天前,最后修改于 296 天前,其中某些信息可能已经过时。

预准备

引包

代码语言:javascript
复制
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

绘图全局设置

代码语言:javascript
复制
# 行内绘图
# % matplotlib inline
plt.style.use('ggplot')  # 绘图风格
plt.rcParams['font.sans-serif'] = ['SimHei']  # 显示中文字体

读取数据并整体观察数据结构

代码语言:javascript
复制
In [3]: col = ['user', 'date', 'product', 'amount']
   ...: df_0 = pd.read_table('./data/CDNOW_master.txt', names=col, sep='\s+')  #  sep='\s+ 列于列之间的分隔为至少一个空格
   ...: df = df_0.copy()
   ...: df
    
Out[3]: 
        user      date  product  amount
0          1  19970101        1   11.77
1          2  19970112        1   12.00
2          2  19970112        5   77.00
3          3  19970102        2   20.76
4          3  19970330        2   20.76
...

In [4]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69659 entries, 0 to 69658
Data columns (total 4 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   user     69659 non-null  int64
 1   date     69659 non-null  int64
 2   product  69659 non-null  int64
 3   amount   69659 non-null  float64
dtypes: float64(1), int64(3)
memory usage: 2.1 MB

分析:观察数据结构可得,数据表一共有69659行、4列,且无空行,其中4列包括user(用户索引列)、date(用户消费时间列)、product(购买产品数量列)、amount(购买总金额列)。

数据的预处理

观察date(用户消费时间列)可发现,其时间格式Pandas未能识别,需要手动将其转换成时间格式列(datetime),方便后续操作。

代码语言:javascript
复制
In [5]: df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')

后续数据分析需要按月来操作,因此需要读取date(用户消费时间列)中的月份,

代码语言:javascript
复制
In [6]: df['month'] = df['date'].astype('datetime64[M]')

注意看这里这里从date(用户消费时间列)中获取月份的方式,并没有使用:

代码语言:javascript
复制
In [7]: df['date'].dt.month

为什么呢?使用.dt.month虽然可以获取月份,但是遇到多个年份中提取月份的话就会出现问题,做个简单小对比:

代码语言:javascript
复制
In [8]: demo = pd.DataFrame({
   ...:     'date': ['2022-07-23', '2021-07-23']
   ...: })
   ...: demo['date'] = pd.to_datetime(demo['date'])
   ...: demo['astype'] = demo['date'].astype('datetime64[M]')
   ...: demo['dt.month'] = demo['date'].dt.month
   ...: demo

Out[8]: 
        date     astype  dt.month
0 2022-07-23 2022-07-01         7
1 2021-07-23 2021-07-01         7

由此可以看出,当遇到多个年份有相同月份的时候,使用.dt.month仅仅可以提取出来月份,但是具体是哪一年的7月,确提取不出来,因此其存在着弊端。

数据分析

月统计量分析

按月份统计产品购买数量、消费金额、消费次数以及消费人数。

代码语言:javascript
复制
df.pivot_table(
    index='month',
    aggfunc={
        'user': 'count',  # 每个月的顾客数量(当同一个顾客下多次订单时,都按照新顾客统计)
        'product': 'count',
        'amount': 'sum'
    })

注意:这种聚合分析方法存在的问题就是,如果一个用户一个月内有多条消费记录,那么其每次都会被当作一个新的消费者记录,即通过'user': 'count'聚合得到的是一个月所有消费记录的数量,并不是本月内有多少不同的顾客来过该店里。

那么如何实现统计每个月内有多少顾客(无重复,比如一个顾客一个月内来了10次店里消费,也按成一次处理)来过店里呢,这就需要分组后做一次去重操作。

代码语言:javascript
复制
df.pivot_table(
    index='month',
    aggfunc={
        'user': lambda x: pd.Series.nunique(x), 
        'product': lambda x: x.nunique(), 
        'amount': 'sum'
    })

使用groupby()方法,然后配合聚合函数也可以达到相同的效果:

代码语言:javascript
复制
df.groupby('month')[['user', 'product', 'amount']].agg({
    'user': lambda x: pd.Series.nunique(x),
    'product': lambda x: pd.Series.nunique(x),
    'amount': 'sum'
})

订单商品数量与订单金额关系分析

代码语言:javascript
复制
df[['product', 'amount']].plot(kind='scatter', x='product', y='amount')

由图中可以看出,大部分订单都有趋向于购买价格少、数量少的特征。

用户消费金额占比(贡献度)

重点使用.cumsum()函数。

代码语言:javascript
复制
user_cumsum = df.pivot_table(index='user', values='amount', aggfunc='sum')
user_cumsum = user_cumsum.sort_values(by='amount').reset_index()
user_cumsum['cumsum_per'] = (user_cumsum['amount'].cumsum() / np.sum(user_cumsum['amount'])).apply(
    lambda x: format(x, '.2%'))
user_cumsum.tail(10)

Out[9]: # 消费累计中贡献度最大的十位用户
        user    amount cumsum_per
23560  15162   4234.45     97.56%
23561   3049   4262.85     97.73%
23562    499   4378.55     97.90%
23563  22279   4490.64     98.08%
23564   6569   4968.00     98.28%
23565   7931   6497.18     98.54%
23566  19339   6552.70     98.80%
23567   7983   6973.07     99.08%
23568  14048   8976.33     99.44%
23569   7592  13990.93    100.00%

用户购买行为分析

每天客流量分析
代码语言:javascript
复制
df.pivot_table(index='user', values='date', aggfunc='min').value_counts().sort_index().plot()
用户最后一次消费时间
代码语言:javascript
复制
df.pivot_table(index='user', values='date', aggfunc='max').value_counts().sort_index().plot()

由此图可以发现,在门店开业初期吸引了大量用户,但是大部分用户仅在前期参与活动后,后期便再也没来过。

RFM模型
  • 最近一次消费 (Recency)——date列最大值
  • 消费频率 (Frequency)——product购买商品数量代替
  • 消费金额 (Monetary)——amount消费金额
代码语言:javascript
复制
rfm_model = df.pivot_table(
    index='user',
    # values=['product', 'amount', 'date'],
    aggfunc={
        'product': 'size',
        'amount': 'sum',
        'date': 'max'
    }
)
# 求出R
rfm_model['R'] = df['date'].max() - rfm_model['date']
rfm_model['R'] = rfm_model['R'].dt.days
# 
rfm_model.rename(columns={
    'amount': 'M',
    'product': 'F'
}, inplace=True)
rfm_model.drop('date', axis=1, inplace=True)

根据RFM模型对用户进行分类:

代码语言:javascript
复制
def check_cus_grade(s):
    label = s.apply(lambda x: '1' if x >= 1 else '0')
    label = label['R'] + label['F'] + label['M']
    grade = {
        '111': '重要价值客户',
        '011': '重要保持客户',
        '101': '重要发展客户',
        '001': '重要挽留客户',
        '110': '一般价值客户',
        '010': '一般保持客户',
        '100': '一般发展客户',
        '000': '一般挽留客户'
    }
    return grade[label]


rfm_model['label'] = rfm_model.apply(lambda x: x - x.mean()).apply(check_cus_grade, axis=1)
rfm_model

RFM模型的可视化:

用户生命周期分析

所谓用户生命周期是指用户第一次消费与最后一次消费的时间间隔。用户最后一次购买日期==第一次购买的日期,说明用户仅仅购买了一次或者用户在同一天内购买了两次。这个时候就需要排除掉仅由一条消费记录的顾客,如果用户仅有一条购买数据,那还谈何生命周期,直接赋值为NaN。

三种不同的实现方法:

代码语言:javascript
复制
# 1、
df.groupby('user').apply(lambda X: X['date'].max() - X['date'].min() if X.shape[0] > 1 else np.NaN)
# 2、
df.groupby('user')['date'].agg(lambda s: (s.max() - s.min()) if len(s) > 1 else np.NaN)
是否多次消费
代码语言:javascript
复制
df.groupby('user').apply(lambda X: 1 if X.shape[0] > 1 else 0).value_counts(normalize=True).plot.pie(autopct='%1.1f%%')
plt.legend(['仅消费一次', '多次消费'])
生命周期分析
代码语言:javascript
复制
user_life_cycle = df.pivot_table(index='user', values='date',
                                 aggfunc=(lambda s: (s.max() - s.min()) if len(s) > 1 else np.NaN))

user_life_cycle.div(np.timedelta64(1, 'D')).plot.hist()
plt.title('所有用户生命周期直方图')
plt.xlabel('生命周期天数')
plt.ylabel('用户人数')

复购率与回购率分析

复购率计算方式:在自然月内,购买多次的用户在总消费人数中的占比(若客户在同一天消费了多次,也称之复购用户)。

代码语言:javascript
复制
user_repurchase_rate = df.pivot_table(index='user', columns='month', values='product', aggfunc='count')

#复购用户:1;非复购的消费用户: 0;自然月没有消费记录的用户: NAN
user_repurchase_rate = user_repurchase_rate.applymap(lambda num: 1 if num > 1 else 0 if num == 1 else np.NaN)

回购率计算方式:在一个时间窗口(一个月)内进行了消费,在下一个窗口内又进行了消费。回购用户:本月消费了,上个月也消费了,记为1;非回购用户:本月消费了,但是上个月未消费,记为0;本月未消费,记为NaN。

代码语言:javascript
复制
def back_purchase(s):
    every_month_status = []
    # 第一个月不会有回购用户
    if s[0] == 1:  # 第一个月消费了
        every_month_status.append(0)  # 记为非回购用户
    else:  # 第一个月未消费
        every_month_status.append(np.NaN)  # 记为NaN

    for i in range(1, len(s)):
        if s[i] == 1:  # 当前月份消费了
            if s[i - 1] == 1:  # 上个月份也消费了
                every_month_status.append(1)  # 回购用户
            else:  # 下个月份未消费
                every_month_status.append(0)  # 非回购用户
        else:  # 当前月份未消费
            every_month_status.append(np.NaN)

    return pd.Series(every_month_status, user_repurchase_rate.columns)

purchase_return = user_repurchase_rate.apply(back_purchase, axis=1)

复购率与回购率的可视化

代码语言:javascript
复制
purchase_return.sum().div(purchase_return.count()).plot(label='回购率')
user_repurchase_rate.sum().div(user_repurchase_rate.count()).plot(label='复购率')
plt.legend()
plt.ylabel('百分比(%)')
plt.title('用户复购率与回购率对比图')
代码语言:javascript
复制
plt.plot(purchase_return.sum(), label='回购人数')
plt.plot(user_repurchase_rate.sum(), label='复购人数')
plt.legend()
plt.ylabel('百分比(%)')
plt.xlabel('month')
plt.title('用户复购人数与回购人数对比图')

总结

1、用户个体特征:每笔订单的金额和商品购买量都集中在区间的低段水平,都是小金额小批量进行购买,此类交易群体,可在丰富产品线和增加促销活动提高转换率和购买率。

2、大部分用户的消费总额和购买总量都集中刚在低段,长尾分布,这个跟用户需求有关,可以对商品进行多元文化价值的赋予,增强其社交价值属性,提高用户的价值需求。

3、用户的消费周期:有二次以上消费的用户,平均68天,所以在50天到60天期间,应该对这批用户进行刺激召回,细致点,比如10天回复满意度,30天发放优惠券,55天的时候提醒优惠券的使用。

4、用户的生命周期:有二次及以上消费的用户的平均生命周期是276天。用户的生命周期分别在20天内与400至500天间,应该在20天内对客户进行引导,促进其再次消费并形成消费习惯,延长其生命周期;在100至400天的用户,也要根据其特点推出有针对性的营销活动,引导其持续消费。

5、新客户的复购率约为12%,老客户的复购率在20%左右;新客户的回购率在15%左右,老客户的回购率在30%左右,需要营销策略积极引导其再次消费及持续消费。

6、用户质量:用户个体消费有一定规律性,大部分用户的消费集中在2000以下,用户消费反应了2/8法则,消费排名前20%的用户贡献了80%的消费额。所以说,狠抓高质量用户是万古不变的道理,这些高质量客户都是“会员”类型,需要专门]为会员优化购物体验,比如专线接听、特殊优惠等等。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 预准备
    • 引包
      • 绘图全局设置
      • 读取数据并整体观察数据结构
        • 数据的预处理
        • 数据分析
          • 月统计量分析
            • 订单商品数量与订单金额关系分析
              • 用户消费金额占比(贡献度)
                • 用户购买行为分析
                  • 每天客流量分析
                  • 用户最后一次消费时间
                  • RFM模型
                • 用户生命周期分析
                  • 是否多次消费
                  • 生命周期分析
                • 复购率与回购率分析
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档