【学习笔记】这是一份CD网站用户消费行为分析报告

这是一份用户消费行为的分析报告

数据来源于网上(秦路老师),是用户在一家CD网站上的消费记录,仅作为学习之用,如有侵权,可联系删除~

0引言

用户消费记录是用户行为的具体体现,通过具体的分析指标对用户行为进行分析,可以更好地了解用户行为,为进一步制定高价值用户管理策略和营销策略提供参考依据。
具体分析指标包括:

  • 进行用户消费趋势的分析
  • 用户个体消费分析
  • 用户消费行为分析
  • 复购率和回购分析

0.1 数据导入

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline      
plt.style.use('ggplot') 
plt.rcParams['font.sans-serif'] = ['SimHei'] #SimHei黑体
plt.rcParams['axes.unicode_minus'] = False  #False 状态下可以显示复数

0.2 数据基本信息

columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table('CDNOW_master.txt',names = columns,sep='\s+')

该数据主要包含以下字段:

  • user_id : 用户ID
  • order_dt : 购买日期
  • order_products : 购买产品数
  • order_amount : 购买金额
df.head()
user_idorder_dtorder_productsorder_amount
0119970101111.77
1219970112112.00
2219970112577.00
3319970102220.76
4319970330220.76
df.info()  #查看数据的基本信息
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69659 entries, 0 to 69658
Data columns (total 4 columns):
user_id           69659 non-null int64
order_dt          69659 non-null int64
order_products    69659 non-null int64
order_amount      69659 non-null float64
dtypes: float64(1), int64(3)
memory usage: 2.1 MB
  • order_dt 购买日期的数据格式不对,后期需要进行修改
df.describe()
user_idorder_dtorder_productsorder_amount
count69659.0000006.965900e+0469659.00000069659.000000
mean11470.8545921.997228e+072.41004035.893648
std6819.9048483.837735e+032.33392436.281942
min1.0000001.997010e+071.0000000.000000
25%5506.0000001.997022e+071.00000014.490000
50%11410.0000001.997042e+072.00000025.980000
75%17273.0000001.997111e+073.00000043.700000
max23570.0000001.998063e+0799.0000001286.010000

通过数据描述可以发现:

  • 大部分订单只消费了少量商品(平均2.4),有一定极值干扰
  • 用户的消费金额比较稳定,平均消费35.89元,中位数在25.98元,有一定极值干扰

0.3 日期数据整理

df['order_dt'] = pd.to_datetime(df.order_dt,format = '%Y%m%d')
df['month'] = df.order_dt.values.astype('datetime64[M]')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69659 entries, 0 to 69658
Data columns (total 5 columns):
user_id           69659 non-null int64
order_dt          69659 non-null datetime64[ns]
order_products    69659 non-null int64
order_amount      69659 non-null float64
month             69659 non-null datetime64[ns]
dtypes: datetime64[ns](2), float64(1), int64(2)
memory usage: 2.7 MB
df.head()
user_idorder_dtorder_productsorder_amountmonth
011997-01-01111.771997-01-01
121997-01-12112.001997-01-01
221997-01-12577.001997-01-01
331997-01-02220.761997-01-01
431997-03-30220.761997-03-01

1. 进行用户消费趋势的分析(按月)

  • 每月消费总金额
  • 每月的消费次数
  • 每月的产品购买数量
  • 每月的消费人数

1.1 每月消费总金额

grouped_month = df.groupby('month')
order_month_amount = grouped_month.order_amount.sum()
order_month_amount.head()
month
1997-01-01    299060.17
1997-02-01    379590.03
1997-03-01    393155.27
1997-04-01    142824.49
1997-05-01    107933.30
Name: order_amount, dtype: float64
plt.figure(figsize=(6, 0.618*6))
plt.title('每月销售额')
plt.ylabel('销售额')
order_month_amount.plot()
plt.savefig('./01',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5EJnePOi-1606388329011)(output_19_0.png)]

由上图可知,销售额在前三个月达到最高峰,后续销售额较为稳定,有轻微下降趋势

1.2 每月的消费次数

plt.figure(figsize=(6, 0.618*6))
plt.title('每月订单数')
plt.ylabel('订单数量')
grouped_month.user_id.count().plot()
plt.savefig('./02',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1JG4AdF1-1606388329012)(output_22_0.png)]

由上图可知,前三个月消费订单数在10000笔左右,后续月份的订单数量则在2500笔左右。

1.3每月的产品购买数量

plt.figure(figsize=(6, 0.618*6))
plt.title('每月产品购买数量')
plt.ylabel('产品购买数量')
grouped_month.order_products.sum().plot()
plt.savefig('./03',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ocwKjpDC-1606388329013)(output_25_0.png)]

由上图可知,前三个月产品购买数量在20000左右,后续月份购买数量下滑,在5500左右,且有递减趋势。

1.4 每月的消费人数

plt.figure(figsize=(6, 0.618*6))
grouped_month.user_id.apply(lambda x:len(x.drop_duplicates())).plot()
plt.title('每月消费人数')
plt.ylabel('人数')
plt.savefig('./04',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5yk2xW0B-1606388329015)(output_28_0.png)]

由上图可知,每月消费人数低于每月消费次数,但差异不大
前三个月每月的消费人数在8000~10000之间,后续月份平均消费人数在2000人左右

  • 数据透视表
df.pivot_table(index = 'month',
              values = ['order_products','order_amount','user_id'],
              aggfunc = { 'order_products':'sum',
                         'order_amount':'sum',
                         'user_id':'count'              
              }).head()
order_amountorder_productsuser_id
month
1997-01-01299060.17194168928
1997-02-01379590.032492111272
1997-03-01393155.272615911598
1997-04-01142824.4997293781
1997-05-01107933.3072752895

除此之外,还可以计算

  • 每月用户平均消费金额的趋势
  • 每月用户平均消费次数的趋势

2. 用户个体消费分析

  • 用户消费金额,消费次数的描述统计
  • 用户消费金额和消费的散点图
  • 用户消费金额的分布图
  • 用户消费次数的分布图
  • 用户累计消费金额占比(百分之多少的用户占了百分之多少的消费额)

2.1 用户消费金额,消费次数的描述统计

grouped_user = df.groupby('user_id')
grouped_user.sum().describe()
order_productsorder_amount
count23570.00000023570.000000
mean7.122656106.080426
std16.983531240.925195
min1.0000000.000000
25%1.00000019.970000
50%3.00000043.395000
75%7.000000106.475000
max1033.00000013990.930000
  • 用户平均购买了7张CD,但是中位值只有3,说明小部分用户购买了大量的CD
  • 用户平均消费了106元,但是中位值只有43元,判断同上,有极值干扰
  • 75%分位点购买数量为7,和均值相同,说明有25%的人买了大于7张CD。

2.2 用户消费金额和消费的散点图

plt.figure(figsize=(6, 0.618*6))
grouped_user.sum().query('order_amount < 6000').plot.scatter(x = 'order_amount',y = 'order_products')
plt.ylabel('购买产品数')
plt.xlabel('购买金额')
plt.savefig('./05',bbox_inches = 'tight')

在这里插入图片描述

2.3 用户消费金额的分布图

plt.figure(figsize=(6, 0.618*6))
grouped_user.sum().order_amount.plot.hist(bins = 20)
plt.xlabel('用户消费金额')
plt.ylabel('用户人数')
plt.title('用户消费金额分布图')
plt.savefig('./06',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9atymVAh-1606388329017)(output_41_0.png)]

从直方图可知,用户消费金额绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常

2.4 用户购买数量分布图

plt.figure(figsize=(6, 0.618*6))
grouped_user.sum().query('order_products < 100 ').order_products.hist(bins = 20)
plt.xlabel('购买数量')
plt.ylabel('用户人数')
plt.title('用户购买数量分布图')
plt.savefig('./07',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zNboMXeb-1606388329018)(output_44_0.png)]

从直方图可知,用户消费金额,绝大部分呈现集中趋势,大部分购买CD数20张内,高消费用户在图上几乎看不到,这是符合消费行为的行业规律。

2.5 用户累计消费金额占比

plt.figure(figsize=(6, 0.618*6))
user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x: x.cumsum()/x.sum())
user_cumsum.reset_index().order_amount.plot()  #为方便作图,这里需要重置索引,否则原索引会变成横坐标
plt.xlabel('用户人数')
plt.ylabel('百分比%')
plt.title('用户累计消费金额占比')
plt.savefig('./08',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VJh2RSa3-1606388329018)(output_47_0.png)]

通过分析累计销售额占比,从图中不难看出用户消费行为基本符合二八定律,80% 的用户贡献了 25% 的消费金额,而 60% 的消费由前 5000 名用户贡献。所以只要维护了这5000 名用户,就能完成 60% 的KPI。

3. 用户消费行为

  • 用户第一次消费(首购)
  • 用户最后一次消费
  • 用户分层
  • RFM模型
  • 新、活跃、回流、流失/不活跃
  • 用户购买周期(按订单)
  • 用户消费周期描述
  • 用户消费周期分布
  • 用户生命周期(按第一次&最后一次消费)
  • 用户生命周期描述
  • 用户生命周期分布

3.1 用户第一次消费(首购)

plt.figure(figsize=(6, 0.618*6))
grouped_user.min().order_dt.value_counts().plot()
plt.xlabel('时间')
plt.ylabel('人数')
plt.savefig('./09',bbox_inches = 'tight')

在这里插入图片描述

用户第一次购买分布,集中在前三个月
其中,在2月11日至2月25日有一次剧烈的波动

3.2 用户最后一次消费

plt.figure(figsize=(6, 0.618*6))
grouped_user.max().order_dt.value_counts().plot()
plt.xlabel('时间')
plt.ylabel('人数')
plt.savefig('./10',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cAe4brUG-1606388329019)(output_54_0.png)]

用户最后一次购买的分布比第一次广
大部分用户最后一次购买,集中在前三个月,说明有很多用户购买了一次后就不再进行购买
随着时间的递增,最后一次购买数也在递增,消费呈现流失上升的状况

user_life = grouped_user.order_dt.agg(['min','max'])
user_life.head()
minmax
user_id
11997-01-011997-01-01
21997-01-121997-01-12
31997-01-021998-05-28
41997-01-011997-12-12
51997-01-011998-01-03
(user_life['min'] == user_life['max']).value_counts()
True     12054
False    11516
dtype: int64

有一半用户就消费了一次

3.3 用户分层

3.3.1 构建RFM模型

rfm = df.pivot_table(index = 'user_id',
                    values = ['order_products','order_amount','order_dt'],
                    aggfunc = {'order_dt':'max',
                              'order_amount':'sum',
                              'order_products':'sum'})
rfm.head()
order_amountorder_dtorder_products
user_id
111.771997-01-011
289.001997-01-126
3156.461998-05-2816
4100.501997-12-127
5385.611998-01-0329
rfm['R'] = -(rfm.order_dt - rfm.order_dt.max())/np.timedelta64(1,'D')  #去除天数的单位,方便计算
rfm.rename(columns = {'order_products':'F','order_amount':'M'},inplace = True)
rfm.head()
Morder_dtFR
user_id
111.771997-01-011545.0
289.001997-01-126534.0
3156.461998-05-281633.0
4100.501997-12-127200.0
5385.611998-01-0329178.0
def rfm_func(x):
    level = x.apply(lambda x: '1' if x >= 0 else '0')
    label = level.R + level.F + level.M
    d = {
        '111':'重要价值客户',
        '011':'重要保持客户',
        '101':'重要发展客户',
        '001':'重要挽留客户',
        '110':'一般价值客户',
        '010':'一般保持客户',
        '100':'一般发展客户',
        '000':'一般挽留客户'
    }
    result = d[label]
    return result

rfm['label'] = rfm[['R','F','M']].apply(lambda x: x - x.mean()).apply(rfm_func,axis=1)
rfm.head()
Morder_dtFRlabel
user_id
111.771997-01-011545.0一般发展客户
289.001997-01-126534.0一般发展客户
3156.461998-05-281633.0重要保持客户
4100.501997-12-127200.0一般挽留客户
5385.611998-01-0329178.0重要保持客户
plt.figure(figsize=(6, 0.618*6))
for label,gropued in rfm.groupby('label'):
    x= gropued['F']
    y = gropued['R']
    
    plt.scatter(x,y,label = label) # 利用循环绘制函数
plt.legend(loc='best') # 图例位置
plt.xlabel('Frequency')
plt.ylabel('Recency')
plt.savefig('./11',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mvgcxvo-1606388329020)(output_65_0.png)]

rfm.groupby('label').count()  
Morder_dtFR
label
一般价值客户77777777
一般保持客户206206206206
一般发展客户14074140741407414074
一般挽留客户3300330033003300
重要价值客户787787787787
重要保持客户4554455445544554
重要发展客户241241241241
重要挽留客户331331331331
rfm.groupby('label').sum()
MFR
label
一般价值客户7181.2865036295.0
一般保持客户19937.45171229448.0
一般发展客户438291.81293466951815.0
一般挽留客户196971.2313977591108.0
重要价值客户167080.8311121358363.0
重要保持客户1592039.62107789517267.0
重要发展客户33028.401263114482.0
重要挽留客户45785.01202356636.0

从RFM分层可知,大部分用户为重要保持用户,但是这是由于极值的影响,所以RFM分层的划分标准应该以业务为准

  • 尽量用小部分的用户覆盖大部分的额度
  • 不要为了数据好看划分等级

3.3.2 按照新、活跃、回流、流失分层用户

pivoted_counts = df.pivot_table(index = 'user_id',
                               columns = 'month',
                               values = 'order_dt',
                               aggfunc = 'count').fillna(0)
pivoted_counts.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
11.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
22.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
31.00.01.01.00.00.00.00.00.00.02.00.00.00.00.00.01.00.0
42.00.00.00.00.00.00.01.00.00.00.01.00.00.00.00.00.00.0
52.01.00.01.01.01.01.00.01.00.00.02.01.00.00.00.00.00.0
df_purchase = pivoted_counts.applymap(lambda x : 1 if x >0 else 0)
df_purchase.tail()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
23566001000000000000000
23567001000000000000000
23568001100000000000000
23569001000000000000000
23570001000000000000000
def active_status(data):
    status =[]
    for i in range(18):
        
        #若本月没有消费
        if data[i] == 0:
            if len(status) > 0:
                if status[i-1] == 'unreg':
                    status.append('unreg')
                else:
                    status.append('unactive')
            else:
                status.append('unreg')
        
        #若本月有消费
        else:
            if len(status) == 0:
                status.append('new')
            else:
                if status[i-1] == 'unactive':
                    status.append('return')
                elif status[i-1]== 'unreg':
                    status.append('new')
                else:
                    status.append('active')
                    
    data = data.astype('object')
    for i in range(18):
        data[i] = status[i]
        
    return data
                

若本月没有消费

  • 若之前是未注册,则依旧是未注册
  • 若之前有消费,则为流失/不活跃
  • 其他情况,为未注册

若本月有消费

  • 若是第一次消费,则为新用户
  • 如果之前有过消费,且上个月为不活跃,则为回流
  • 如果上个月为未注册,则为新用户
  • 除此之外,为活跃
purchase_stats = df_purchase.apply(active_status,axis = 1)
purchase_stats.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
1newunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactive
2newunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactiveunactive
3newunactivereturnactiveunactiveunactiveunactiveunactiveunactiveunactivereturnunactiveunactiveunactiveunactiveunactivereturnunactive
4newunactiveunactiveunactiveunactiveunactiveunactivereturnunactiveunactiveunactivereturnunactiveunactiveunactiveunactiveunactiveunactive
5newactiveunactivereturnactiveactiveactiveunactivereturnunactiveunactivereturnactiveunactiveunactiveunactiveunactiveunactive
purchase_stats_ct = purchase_stats.replace('unreg',np.NaN).apply(lambda x: pd.value_counts(x))
purchase_stats_ct
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
activeNaN1157.016811773.0852.0747.0746.0604.0528.0532.0624.0632.0512.0472.0571.0518.0459.0446.0
new7846.08476.07248NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
returnNaNNaN5951049.01362.01592.01434.01168.01211.01307.01404.01232.01025.01079.01489.0919.01029.01060.0
unactiveNaN6689.01404620748.021356.021231.021390.021798.021831.021731.021542.021706.022033.022019.021510.022133.022082.022064.0

新用户前三月较多,后期没有增加,流失用户逐渐增加,回流用户和活跃用户逐渐减少

purchase_stats_ct.fillna(0).T.head()
activenewreturnunactive
month
1997-01-010.07846.00.00.0
1997-02-011157.08476.00.06689.0
1997-03-011681.07248.0595.014046.0
1997-04-011773.00.01049.020748.0
1997-05-01852.00.01362.021356.0
plt.figure(figsize=(20, 0.618*20))
purchase_stats_ct.fillna(0).T.plot.area() #绘制面积图
plt.ylabel('人数')
plt.savefig('./12',bbox_inches = 'tight')
<Figure size 1440x889.92 with 0 Axes>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ss6oEt7O-1606388329021)(output_78_1.png)]

由面积图,蓝色和灰色区域占大面积,可以不看,因为这只是某段时间消费过的用户的后续行为。其次红色代表的活跃用户非常稳定,是属于核心用户,以及紫色的回流用户,这两个分层相加,就是消费用户人数占比(后期没有新增用户)

  • 各类用户的占比
purchase_stats_ct.fillna(0).T.apply(lambda x: x/ x.sum(),axis = 1) #各类用户的占比
activenewreturnunactive
month
1997-01-010.0000001.0000000.0000000.000000
1997-02-010.0708860.5192990.0000000.409815
1997-03-010.0713190.3075100.0252440.595927
1997-04-010.0752230.0000000.0445060.880272
1997-05-010.0361480.0000000.0577850.906067
1997-06-010.0316930.0000000.0675430.900764
1997-07-010.0316500.0000000.0608400.907510
1997-08-010.0256260.0000000.0495550.924820
1997-09-010.0224010.0000000.0513790.926220
1997-10-010.0225710.0000000.0554520.921977
1997-11-010.0264740.0000000.0595670.913958
1997-12-010.0268140.0000000.0522700.920916
1998-01-010.0217230.0000000.0434870.934790
1998-02-010.0200250.0000000.0457790.934196
1998-03-010.0242260.0000000.0631740.912601
1998-04-010.0219770.0000000.0389900.939033
1998-05-010.0194740.0000000.0436570.936869
1998-06-010.0189220.0000000.0449720.936105
plt.figure(figsize=(10, 10*0.618))
rate = purchase_stats_ct.fillna(0).T.apply(lambda x: x/ x.sum(),axis = 1)
plt.plot(rate['return'],label='return')
plt.plot(rate['active'],label='active')
plt.legend()
plt.savefig('./13',bbox_inches = 'tight')
<matplotlib.legend.Legend at 0x240974b0688>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w83t4B8m-1606388329022)(output_82_1.png)]

由上表可知,每月的用户消费状态变化

  • 回流用户比:某个时间段内回流用户在总用户中的占比
    • 由图可知,用户每月回流用户比占 5% ~ 8% 之间,有下降趋势,说明客户有流失倾向。
  • 回流用户率:上月有多少不活跃用户在本月消费
    • 由于这份数据的不活跃用户量基本不变,所以这里的回流率,也近似等于回流比
  • 活跃用户比:某个时间段内活跃用户在总用户中的占比。
    • 活跃用户的占比在 3% ~ 5%间,下降趋势更显著,活跃用户可以看作连续消费用户,忠诚度高于回流用户。

结合活跃用户和回流用户看,在后期的消费用户中,60%是回流用户,40%是活跃用户,整体用户质量相对不错。也进一步说明前面用户消费行为分析中的二八定律,反映了在消费领域中,狠抓高质量用户是不变的道理。

3.4 用户购买周期

#订单时间间隔
order_diff = grouped_user.apply(lambda x : x.order_dt - x.order_dt.shift()) #shift函数使数据向下平移一位
order_diff.head(10)
user_id   
1        0        NaT
2        1        NaT
         2     0 days
3        3        NaT
         4    87 days
         5     3 days
         6   227 days
         7    10 days
         8   184 days
4        9        NaT
Name: order_dt, dtype: timedelta64[ns]
order_diff.describe()
count                      46089
mean     68 days 23:22:13.567662
std      91 days 00:47:33.924168
min              0 days 00:00:00
25%             10 days 00:00:00
50%             31 days 00:00:00
75%             89 days 00:00:00
max            533 days 00:00:00
Name: order_dt, dtype: object
#订单周期分布图
plt.figure(figsize=(6, 0.618*6))
(order_diff/ np.timedelta64(1,'D')).hist(bins=20)
plt.xlabel('周期(天数)')
plt.ylabel('人数')
plt.savefig('./14',bbox_inches = 'tight')

在这里插入图片描述

  • 订单周期呈指数分布
  • 用户的平均购买周期是 68 天
  • 绝大部分用户的购买周期低于 100 天
  • 用户生命周期图是典型的长尾图,大部分用户的消费间隔确实比较短。
    不妨将时间召回点设为消费后立即赠送优惠券,消费后10天询问用户CD怎么样,消费后30天提醒优惠券到期,消费后60天短信推送。

3.5 用户生命周期

#最后一次购买的时间减去首购时间
(user_life['max']-user_life['min']).describe()
count                       23570
mean     134 days 20:55:36.987696
std      180 days 13:46:43.039788
min               0 days 00:00:00
25%               0 days 00:00:00
50%               0 days 00:00:00
75%             294 days 00:00:00
max             544 days 00:00:00
dtype: object
plt.figure(figsize=(6, 0.618*6))
((user_life['max']- user_life['min'])/np.timedelta64(1,'D')).hist(bins = 40)
plt.xlabel('周期(天数)')
plt.ylabel('人数')
plt.savefig('./15',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RaRS9612-1606388329023)(output_92_0.png)]

  • 用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
  • 用户均消费134天,但是平均数不靠谱,中位数 0 天,大部分用户第一次消费也是最后一次,这批属于低质量用户,而最大的是 544 天,几乎是数据集的总天数,这部分用户属于核心用户。
plt.figure(figsize=(6, 0.618*6))
u_1 = (user_life['max']- user_life['min']).reset_index()[0]/ np.timedelta64(1,'D') 
u_1 [u_1 > 0].hist(bins=40)  #排除只购买一次的用户后的用户生命周期直方图
plt.xlabel('周期(天数)')
plt.ylabel('人数')
plt.savefig('./16',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pXXChp3Z-1606388329023)(output_94_0.png)]

  • 过滤掉周期为 0 的用户后,图像呈双峰结构;
  • 部分低质用户,虽然消费两次,但还是不能持续消费,要想提高用户转化率,应该往用户首次消费 30 天内尽量引导;
  • 少部分用户集中在 50 - 300 天,属于普通用户,忠诚度一般。
  • 集中在 400 天以后的,是高质量用户了,后期人数还在增加,这批用户已经属于核心用户了,忠诚度极高,尽量维护这批用户的利益。

4.复购率和回购分析

  • 复购率
  • 自然月内,购买多次的用户占比
  • 回购率
  • 曾经购买过的用户在某一时期内的再次购买的占比
pivoted_counts.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
11.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
22.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.00.0
31.00.01.01.00.00.00.00.00.00.02.00.00.00.00.00.01.00.0
42.00.00.00.00.00.00.01.00.00.00.01.00.00.00.00.00.00.0
52.01.00.01.01.01.01.00.01.00.00.02.01.00.00.00.00.00.0
  • 整理数据透视表
purchase_r = pivoted_counts.applymap(lambda x : 1 if x > 1 else np.NaN if x ==0 else 0) #消费1次以上为1,消费0次为空,其他为0
purchase_r.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
10.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
21.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
30.0NaN0.00.0NaNNaNNaNNaNNaNNaN1.0NaNNaNNaNNaNNaN0.0NaN
41.0NaNNaNNaNNaNNaNNaN0.0NaNNaNNaN0.0NaNNaNNaNNaNNaNNaN
51.00.0NaN0.00.00.00.0NaN0.0NaNNaN1.00.0NaNNaNNaNNaNNaN

4.1复购率

plt.figure(figsize=(6, 0.618*6))
(purchase_r.sum()/purchase_r.count()*100).plot(figsize=(10,4)) #宽为10,高为4的图形  
plt.ylabel('百分比%')
plt.savefig('./17',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VMM1ycYP-1606388329024)(output_101_0.png)]

复购率稳定在20%左右,前三个月因为有大量新用户涌入,而这批用户只购买了一次,所以导致复购率降低

4.2 回购率

df_purchase.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
1100000000000000000
2100000000000000000
3101100000010000010
4100000010001000000
5110111101001100000
def purchase_back(data):
    status=[]
    for i in range(17):
        if data[i] == 1:
            if data[i+1] == 1:
                status.append(1)
            if data[i+1] == 0:
                status.append(0)
        else:
            status.append(np.NaN)
    status.append(np.NaN) #填充最后一个月的数据
    
    data = data.astype('object') 
    for i in range(17):
        data[i] = status[i]
    return data
purchase_b = df_purchase.apply(purchase_back,axis = 1)
purchase_b.head()
month1997-01-011997-02-011997-03-011997-04-011997-05-011997-06-011997-07-011997-08-011997-09-011997-10-011997-11-011997-12-011998-01-011998-02-011998-03-011998-04-011998-05-011998-06-01
user_id
10.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN0
20.0NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaN0
30.0NaN1.00.0NaNNaNNaNNaNNaNNaN0.0NaNNaNNaNNaNNaN0.00
40.0NaNNaNNaNNaNNaNNaN0.0NaNNaNNaN0.0NaNNaNNaNNaNNaN0
51.00.0NaN1.01.01.00.0NaN0.0NaNNaN1.00.0NaNNaNNaNNaN0
plt.figure(figsize=(6, 0.618*6))
(purchase_b.sum()/purchase_b.count()).plot(figsize = (10,4))
plt.ylabel('百分比%')
plt.savefig('./18',bbox_inches = 'tight')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8o1y3Eci-1606388329024)(output_107_0.png)]

  • 由回购率图可以看出,用户回购率高于复购率,约在 30% 左右,波动性较强。新用户回购率在 15 % 左右,与老用户相差不大。
  • 由人数分布图发现,回购人数在前三月之后趋于稳定,所以波动产生的原因可能由于营销淡旺季导致,但之前复购用户的消费行为与会回购用户的行为大致相同,可能有一部分用户重合,属于优质用户。
  • 结合回购率和复购率分析,发现新客的整体忠诚度低于老客,老客的回购率较好,消费频率稍低,这是该网站的用户消费特征。

5.总结

  • 通过用户消费趋势分析发现,由于新用户的加入,前3个月业绩较好,销量、销售额、订单数量和月消费人数都在较高水平,而后有所下滑,并维持在一定水平内;
  • 通过用户个体消费分析发现,60%的销售额是由5000名左右的用户贡献的,也就是说小部分用户贡献了绝大多数的业绩,这部分属于优质用户,需要重点关注;
  • 用户消费行为分析中,利用RFM模型可以对用户进行分层,并针对不同用户采取不同的营销策略,还可以根据用户生命周期数据,采取措施提高用户粘性,延长生命周期;
  • 复购率和回购分析中,可以发现新客的整体忠诚度低于老客,老客的回购率较好,消费频率稍低。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值