​数据分析项目-用户消费行为分析

目录

导入及分析

第一部分:数据清洗

导包

数据加载&分析数据

数据清洗

第二部分:按月数据分析

分析方向:用户、订单、消费趋势 

消费趋势的分析

1. 每月的消费总金额

2. 每月的消费次数

3. 每月的产品购买量

4. 每月的消费人数(去重)

5. 将上述趋势分析用透视表展示(pivot_table)

第三部分:用户个体消费数据分析

1. 用户消费金额和消费次数的描述统计

2.用户消费金额和消费次数的散点图

3. 用户消费金额的分布图(二八法则)

4. 用户消费次数的分布图(二八法则)

5. 用户累计消费金额的占比(百分之多少的用户占了百分之多少的消费额)

第四部分:用户消费行为分析

1.用户第一次消费(首购) 

2. 用户最后一次消费

3. 新老客户的消费比

4. 用户的购买周期

5. 用户分层(使用透视表)

5.1. 用户分层二:RFM 

5.2. 用户分层三:求和

5.3. 用户分层四:计数

5.4. 用户分层五:给不同层次客户用颜色区分设置 

5.5. 用户分层六:用户生命周期 

5.6. 用户分层七:用户购买周期(按订单)

6. 复购率和回购率的分析


 

导入及分析

项目名称:CD用户消费行为分析

项目概述:本项目主要利用Numpy,Pandas,matplotlib等三个工具进行数据的处理,来分析用户消费行为。数据来源与CDNow网站的用户购买明细。

分析步骤:

第一部分:数据清洗

    1. 数据类型的转换
    2. 空值处理
    3. 异常值处理

第二部分:按月数据分析

    1. 每月的消费总金额
    2. 每月的消费次数
    3. 每月的产品购买量
    4. 每月的消费人数

第三部分:用户个体消费数据分析

    1. 用户消费金额和消费次数的描述统计
    2. 用户消费金额和消费次数的散点图
    3. 用户消费金额的分布图
    4. 用户消费次数的分布图
    5. 用户累计消费金额的占比

第四部分:用户消费行为分析

    1. 用户第一次消费时间
    2. 用户最后一次消费时间
    3. 新老客户消费比
    4. 用户分层
    5. 用户购买周期
    6. 用户生命周期

第一部分:数据清洗

导包

#导入需要的包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from datetime import  datetime

数据加载&分析数据

字段含义:

        user_id:用户ID

        order_dt:购买日期

        order_product:购买产品的数量

        order_amount:购买金额

消费行业或者是电商行业一般是通过订单数、订单额、购买日期,用户ID这四个字段来分析的,基本上这四个字段就能缑进行很丰富的分析。

# 因为原始数据中不包含表头,在这里定义好赋值
columns=['user_id','order_dt','order_products','order_amount']
# 参数 sep='\s+',用于匹配任意空白符
df=pd.read_csv('./data/CDNOW_master.txt',names=columns,sep='\s+')
print(df.head())
print(df.info())

输出结果

  user_id  order_dt  order_products  order_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
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 69659 entries, 0 to 69658
Data columns (total 4 columns):#   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  0   user_id         69659 non-null  int64  1   order_dt        69659 non-null  int64  2   order_products  69659 non-null  int64  3   order_amount    69659 non-null  float64
dtypes: float64(1), int64(3)
memory usage: 2.1 MB
NoneProcess finished with exit code 0

分析:

1.数据完整,没有空数据

2.order_dt是int类型,需要将其转换成时间类型

3.用户可能在同一天内重复购买(如:ID为2的顾客在1月12日这一天内购买了两次)

4.因为后面要按月分析,需要添加一列month

数据清洗

#数据清洗
df=date1.copy()
# format='%Y%m%d' 这里要指明格式,否则可能出错
df['order_dt']=pd.to_datetime(df['order_dt'],format='%Y%m%d')
# 增加一列 month
df['month']=df['order_dt'].values.astype('datetime64[M]')
print(df.head())

输出结果

   user_id   order_dt  order_products  order_amount      month
0        1 1997-01-01               1         11.77 1997-01-01
1        2 1997-01-12               1         12.00 1997-01-01
2        2 1997-01-12               5         77.00 1997-01-01
3        3 1997-01-02               2         20.76 1997-01-01
4        3 1997-03-30               2         20.76 1997-03-01Process finished with exit code 0

分析:

describe()是描述统计:

            user_id  order_products  order_amount
count  69659.000000    69659.000000  69659.000000
mean   11470.854592        2.410040     35.893648
std     6819.904848        2.333924     36.281942
min        1.000000        1.000000      0.000000
25%     5506.000000        1.000000     14.490000
50%    11410.000000        2.000000     25.980000
75%    17273.000000        3.000000     43.700000
max    23570.000000       99.000000   1286.010000Process finished with exit code 0

分析 

1. 大部分的订单只消费了少量的商品(平均2.4),有一定的极值干扰

2. 用户的消费金额比较稳定,平均消费在35.8元,中位数在25.9元,有一定的极值干扰。

3. 用户平均每笔订单购买2.4个商品,标准差在2.3,稍具波动性。中位数2个商品,75分位数3个商品, 说明绝大部分订单的购买量都不多。最大值在99个,数字比较高。购买金额的情况差不多,大部分 订单集中在小额

4. 一般而言,消费类的数据分布都是长尾形。大部分用户都是小额,然而小部分用户贡献了收入的大头, 俗称二八。

第二部分:按月数据分析

分析方向:用户、订单、消费趋势 

消费趋势的分析

# 查看一下df的列,方便操作
print(df.columns)

输出结果

Index(['user_id', 'order_dt', 'order_products', 'order_amount', 'month'], dtype='object')

1. 每月的消费总金额

#每月消费总金额
# 根据 month分组统计购买金额总和
order_amt_mon=df.groupby('month')['order_amount'].sum()
print(order_amt_mon.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: float64Process finished with exit code 0

绘图

#绘图
order_amt_mon.plot(c='red')
plt.show()

 分析:

可以看到,97年1,2,3月销量很高,每月平局约3.6万,后期销量趋于平稳,每月在1万左右波动

2. 每月的消费次数

#2. 每月的消费次数
order_amt_count=df.groupby('month')['user_id'].count()
#绘图
order_amt_count.plot(c='orange')
plt.show()

 分析:

前三个月平均消费订单在1万左右,后续月份趋于平稳,约在2500单每月

3. 每月的产品购买量

#3. 每月的产品购买量
order_products_sum=df.groupby('month')['order_products'].sum()
#绘图
order_products_sum.plot(c='b')
plt.show()

分析:

前3个月产品购买数量平均在24000左右,后期下降趋于平稳,约6000每月。原因猜想:

    1.用户层面,早期用户中有异常值;

    2. 公司层面,在搞促销等。因为只有销售数据,所以暂时无法判断具体原因。

4. 每月的消费人数(去重)

 每月的消费人数(去重)去重的原因:一个人可能在一个月内多次消费 

nunique表示统计去重后的个数

#4. 每月的消费人数(去重)去重的原因:一个人可能在一个月内多次消费
user_id_count=df.groupby('month')['user_id'].nunique()
user_id_count.plot(c='g')
plt.show()

分析:

每个月的消费人数小于每月的消费次数,但是区别不大。前3个月月均消费人数在9000左右,后续月均2000不到,一样是前期消费人多,后期平稳的趋势。

5. 将上述趋势分析用透视表展示(pivot_table)

#5. 将上述趋势分析用透视表展示(pivot_table)
df_pivot_table=df.pivot_table(index='month',values=['user_id',  'order_products', 'order_amount'],aggfunc={'user_id':'count','order_amount':'sum','order_products':'sum'})
print(df_pivot_table.head())

输出结果

           order_amount  order_products  user_id
month                                            
1997-01-01     299060.17           19416     8928
1997-02-01     379590.03           24921    11272
1997-03-01     393155.27           26159    11598
1997-04-01     142824.49            9729     3781
1997-05-01     107933.30            7275     2895Process finished with exit code 0

分析:(解决一个需求可能会有很多种方法,具体看哪个更方便,更简单)

     数据透视表是更简单的方法,有了透视表,用里面的数据绘图也是狠方便的。

第三部分:用户个体消费数据分析

上面是通过维度月,来看总体趋势。下面对个体进行分析,看消费能力如何。 大致分为以下五个方向:

1. 用户消费金额和消费次数的描述统计;

2. 用户消费金额和消费次数的散点图;

3. 用户消费金额的分布图(二八法则);

4. 用户消费次数的分布图;

5. 用户累计消费金额的占比(百分之多少的用户占了百分之多少的消费额)

1. 用户消费金额和消费次数的描述统计

#1. 用户消费金额和消费次数的描述统计
df.groupby('user_id')['order_amount'].sum() #每一个用户消费的总金额
df.groupby('user_id').count()['order_dt'] #每一个用户消费的总金额
group_user=df.groupby('user_id')
print(group_user.sum().describe())

输出结果

       order_products  order_amount
count    23570.000000  23570.000000
mean         7.122656    106.080426
std         16.983531    240.925195
min          1.000000      0.000000
25%          1.000000     19.970000
50%          3.000000     43.395000
75%          7.000000    106.475000
max       1033.000000  13990.930000Process finished with exit code 0

分析:

1. 从用户角度看,每位用户平均购买7件商品,最多的用户买了1033件。

2. 用户平均消费额(客单价)100元,标准差是240,结合分位数和最大值看,平均值和75分位接近。

结论:肯定存在小部分高额消费用户,小部分的用户占了消费的大头,符合二八法则。

2.用户消费金额和消费次数的散点图

#2.用户消费金额和消费次数的散点图
user_amount_sum=df.groupby('user_id')['order_amount'].sum() #每一个用户消费的总金额
user_product_sum=df.groupby('user_id')['order_products'].sum() #每一个用户消费的总次数
plt.scatter(user_product_sum,user_amount_sum)
plt.show()
#方法2
group_user.sum().query('order_amount<4000').plot(kind='scatter',x='order_amount',y='order_products')
plt.show()

绘制图形

分析:

  通过绘制用户的散点图,用户比较健康而且规律性很强。因为这是CD网站的销售数据,商品比较单一,金额和商品质量的关系 也呈线性,没几个离群点。

3. 用户消费金额的分布图(二八法则)

#3. 用户消费金额的分布图(二八法则)
group_user.sum().query('order_amount<=1000')['order_amount'].plot(kind='hist',bins=20)
plt.show()

 分析:

1. 从直方图可知,大部分用户的消费能力确实不高,绝大部分集中在很低的消费档次。高消费用户在图上几乎看不到。这也确实 符合消费行为的行业规律。

2. 虽然有极值干扰了我们的数据,但是大部分用户还是集中在比较低的消费档次。

4. 用户消费次数的分布图(二八法则)

#4. 用户消费次数的分布图(二八法则)
group_user.sum().query('order_products<100')['order_products'].plot(kind='hist',bins=40)
plt.show()

5. 用户累计消费金额的占比(百分之多少的用户占了百分之多少的消费额)

# cumsum() 滚动累加求和
user_cumsum=(group_user.sum().sort_values('order_amount').cumsum()) / (2500315.63)
print(user_cumsum)

输出结果

        order_products  order_amount
user_id                              
10175      3.999495e-07      0.000000
4559       7.998990e-07      0.000000
1948       1.199849e-06      0.000000
925        1.599798e-06      0.000000
10798      1.999748e-06      0.000000
...                 ...           ...
7931       6.599847e-02      0.985405
19339      6.614965e-02      0.988025
7983       6.636402e-02      0.990814
14048      6.677717e-02      0.994404
7592       6.714392e-02      1.000000[23570 rows x 2 columns]Process finished with exit code 0

绘图

#绘图
user_cumsum.reset_index().order_amount.plot()
plt.show()

 分析:

按用户消费金额进行升序排序,由图可知50%的用户仅贡献了15%的销售额。而排名前5000的用户就贡献了60%的消费额

也就是说,只要维护好这5000个客户,就可以完成业绩KPI的60%,如果能把5000个用户运营的更好就可以占比70%-80%甚至更高。

第四部分:用户消费行为分析

用户第一次消费(首购)

在很多行业中首购是一个很重要的维度,它和渠道信息息息相关,尤其针对客单价比较高客户留存率比较低的行业,第一次客户从哪里来可以拓展出很多运营方式。

用户最后一次消费

新老客户消费比

多少客户仅消费了一次   每月新客占比

用户分层

 RFM   新、老、活跃、流失

 用户购买周期(按订单)

用户消费周期描述   用户消费周期分布

用户生命周期(按第一次&最后一次消费)

 用户生命周期描述   用户生命周期分布

1.用户第一次消费(首购) 

求月份的最小值,即用户消费行为中的第一次消费时间 

#求月份的最小值,即用户消费行为中的第一次消费时间
group_user=df.groupby('user_id')
min_month=group_user['month'].min().value_counts()
print(min_month)

通过统计结果发现:所有用户第一次消费都集中在前3个月   df['user_id'].unique().size---查看用户总数

[23570 rows x 2 columns]
1997-02-01    8476
1997-01-01    7846
1997-03-01    7248
Name: month, dtype: int64Process finished with exit code 0

2. 用户最后一次消费

#求月份的最大值,即用户消费行为中的最后消费时间
max_month=group_user['month'].max().value_counts()
print(max_month)

输出结果

Name: month, dtype: int64
1997-02-01    4912
1997-03-01    4478
1997-01-01    4192
1998-06-01    1506
1998-05-01    1042
1998-03-01     993
1998-04-01     769
1997-04-01     677
1997-12-01     620
1997-11-01     609
1998-02-01     550
1998-01-01     514
1997-06-01     499
1997-07-01     493
1997-05-01     480
1997-10-01     455
1997-09-01     397
1997-08-01     384
Name: month, dtype: int64

消费者最后一天绘图

#消费者最后一天绘图
group_user['order_dt'].max().value_counts().plot()
plt.show()

将第一次消费与最后一次消费做分析

cha=group_user['order_dt'].agg(['min','max'])
print(cha)
              min        max
user_id                      
1       1997-01-01 1997-01-01
2       1997-01-12 1997-01-12
3       1997-01-02 1998-05-28
4       1997-01-01 1997-12-12
5       1997-01-01 1998-01-03
...            ...        ...
23566   1997-03-25 1997-03-25
23567   1997-03-25 1997-03-25
23568   1997-03-25 1997-04-22
23569   1997-03-25 1997-03-25
23570   1997-03-25 1997-03-26[23570 rows x 2 columns]Process finished with exit code 0

 分析:

观察用户最后一次购买时间发现,用户最后一次消费比第一次消费分布广,大部分最后一次消费集中在前三个月

说明很多客户购买一次后就不再购买。随着时间的增长,最后一次购买数也在递增,消费呈现流失上升的情况,用户忠诚度在慢慢下降。

3. 新老客户的消费比

  • 消费一次为新用户
  • 消费多次为老用户
  • 判定:如果用户第一次消费时间和最后一次消费时间一样,则该用户只消费了一次
  • group_user['order_dt'].agg(['min','max'])#agg对分组后的结果进行多种指定聚合
#3. 新老客户的消费比
user_life=group_user['order_dt'].agg(['min','max'])
print(user_life.head())
               min        max
user_id                      
1       1997-01-01 1997-01-01
2       1997-01-12 1997-01-12
3       1997-01-02 1998-05-28
4       1997-01-01 1997-12-12
5       1997-01-01 1998-01-03Process finished with exit code 0

分析: 

user_id为1的用户第一次消费时间和最后一次消费时间相同,说明他只消费了一次

4. 用户的购买周期

#4. 用户的购买周期
print((user_life['min']==user_life['max']).value_counts())

输出结果

True     12054
False    11516
dtype: int64

分析

可以看到,有一半的用户只消费了一次

5. 用户分层(使用透视表)

rfm = df.pivot_table(index='user_id',values=['order_products','order_amount','order_dt'],aggfunc={'order_products':'sum','order_amount':'sum','order_dt':'max'})print(rfm.head())# order_products--求消费产品总数、order_amount---求消费总金额、order_dt--求最近一次消费时间
         order_amount   order_dt  order_products
user_id                                         
1               11.77 1997-01-01               1
2               89.00 1997-01-12               6
3              156.46 1998-05-28              16
4              100.50 1997-12-12               7
5              385.61 1998-01-03              29Process finished with exit code 0
  • rfm 距今天数 增加一列 
  • -(rfm.order_dt - rfm.order_dt.max())结果为时间类型,将时间格式转化为整数或者浮点数的形式,
  • # 可以除以单位‘D’,也可以用astype转化 
#rfm 距今天数 增加一列
#-(rfm.order_dt - rfm.order_dt.max())结果为时间类型,将时间格式转化为整数或者浮点数的形式,
# 可以除以单位‘D’,也可以用astype转化
rfm['R']=-(rfm['order_dt']-rfm['order_dt'].max())/np.timedelta64(1,'D')
rfm.rename(columns={'order_products':'F','order_amount':'M'},inplace=True)
print(rfm.head())

输出结果

              M   order_dt   F      R
user_id                              
1         11.77 1997-01-01   1  545.0
2         89.00 1997-01-12   6  534.0
3        156.46 1998-05-28  16   33.0
4        100.50 1997-12-12   7  200.0
5        385.61 1998-01-03  29  178.0

分析:

R表示客户最近一次交易的时间间隔,M表示客户在最近一段时间内交易的金额。

F表示客户在最近一段时间内交易的次数。 F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。

M表示客户在最近一段时间内交易的金额。 M值越大,表示客户价值越高,反之则表示客户价值越低。

5.1. 用户分层二:RFM 

def rfm_func(x):level=x.apply(lambda x : '1' if x>=0 else '0')label=level.R+level.F+level.Mdict={'111':'重要价值客户','011':'重要保持客户','101':'重要挽留客户','001':'重要发展客户','110':'一般价值客户','010':'一般保持客户','100':'一般挽留客户','000':'一般发展客户'}result = dict[label]return result# 用户分层,这里使用平均数
rfm['label'] = rfm[['R','F','M']].apply(lambda x : x - x.mean()).apply(rfm_func,axis=1)
print(rfm.head())

输出结果

              M   order_dt   F      R   label
user_id                                      
1         11.77 1997-01-01   1  545.0  一般挽留客户
2         89.00 1997-01-12   6  534.0  一般挽留客户
3        156.46 1998-05-28  16   33.0  重要保持客户
4        100.50 1997-12-12   7  200.0  一般发展客户
5        385.61 1998-01-03  29  178.0  重要保持客户

5.2. 用户分层三:求和

#5. 用户分层三:求和
label_sum=rfm.groupby('label').sum()
print(label_sum)
                 M       F          R
label                                
一般价值客户     7181.28     650    36295.0
一般保持客户    19937.45    1712    29448.0
一般发展客户   196971.23   13977   591108.0
一般挽留客户   438291.81   29346  6951815.0
重要价值客户   167080.83   11121   358363.0
重要保持客户  1592039.62  107789   517267.0
重要发展客户    45785.01    2023    56636.0
重要挽留客户    33028.40    1263   114482.0Process finished with exit code 0

分析:

M表示不同层次客户累计消费金额,重要保持客户最高

5.3. 用户分层四:计数

#5. 用户分层四:计数
label_count=rfm.groupby('label').count()
print(label_count)

分析:

不同层次用户的消费人数,之前重要保持客户的累计消费金额最高,这里人数排第2,但与一般挽留用户人数差距比较大

5.4. 用户分层五:给不同层次客户用颜色区分设置 

rfm.loc[rfm.label == '重要价值客户','color'] = 'g'
# ~:表示求非
rfm.loc[~(rfm.label == '重要价值客户'),'color'] = 'r'
rfm.plot('F','R',kind='scatter',c=rfm.color)
plt.show()

 

 分析:

1. 从RFM分层可知,大部分用户为重要保持客户,但是这是由于极值的影响,所以RFM的划分应该尽量以业务为准。 尽量用小部分的用户覆盖大部分的额度,不能为了数据好看划分等级。

2. RFM是人工使用象限法把数据划分为几个立方体,立方体对应相应的标签,我们可以把标签运用到业务层面上。 比如重要保持客户贡献金额最多159203.62,我们如何与业务方配合把数据提高或者维护;而重要发展客户 和重要挽留客户他们有一段时间没消费了,我们如何把他们拉回来。

5.5. 用户分层六:用户生命周期 

pivoted_counts = df.pivot_table(index='user_id',columns='month',values='order_dt',aggfunc='count',fill_value=0)
print(pivoted_counts.head())
month    1997-01-01  1997-02-01  1997-03-01  ...  1998-04-01  1998-05-01  1998-06-01
user_id                                      ...                                    
1                 1           0           0  ...           0           0           0
2                 2           0           0  ...           0           0           0
3                 1           0           1  ...           0           1           0
4                 2           0           0  ...           0           0           0
5                 2           1           0  ...           0           0           0[5 rows x 18 columns]Process finished with exit code 0

分析:

用户每个月的消费次数,对于生命周期的划分只需要知道用户本月是否消费,消费次数在这里并不重要,需要将模型进行简化

注:使用数据透视表时,要明确获得什么结果。

# 简化
df_purchase = pivoted_counts.applymap(lambda x: 1 if x>0 else 0)
print(df_purchase.head())
month    1997-01-01  1997-02-01  1997-03-01  ...  1998-04-01  1998-05-01  1998-06-01
user_id                                      ...                                    
1                 1           0           0  ...           0           0           0
2                 1           0           0  ...           0           0           0
3                 1           0           1  ...           0           1           0
4                 1           0           0  ...           0           0           0
5                 1           1           0  ...           0           0           0[5 rows x 18 columns]

分析:

对于尾部数据,user_id 2w+的数据是有一些问题的,因为从实际业务场景来说,一月二月他们都没有注册,三月份才是第一次消费。这里需要进行判断将第一次消费作为生命周期的起始,不能从一月份开始就粗略的计算。

一下算法为固定算法 

# 用户生命周期状态变化def active_status(data):ur = 'unreg'    #未注册ua = 'unactive' #不活跃n = 'new'       #新用户a = 'active'    #活跃r = 'return'    #回流用户:上个月不活跃,这个月活跃status = []for i in range(18):#若本月没有消费if data[i] == 0:if len(status) > 0:if n not in status:status.append(ur)else:status.append(ua)else:status.append(ur)#若本月消费else:if len(status) == 0:status.append(n)else:if n not in status:status.append(n)elif status[-1] == ua:status.append(r)else:status.append(a)# 不能直接返回 status,否则会失去表头    ---重点return pd.Series(status, index = df_purchase.columns)pivoted_status = df_purchase.apply(active_status,axis = 1)pivoted_status.head()

输出结果

month   1997-01-01 1997-02-01 1997-03-01  ... 1998-04-01 1998-05-01 1998-06-01
user_id                                   ...                                 
1              new   unactive   unactive  ...   unactive   unactive   unactive
2              new   unactive   unactive  ...   unactive   unactive   unactive
3              new   unactive     return  ...   unactive     return   unactive
4              new   unactive   unactive  ...   unactive   unactive   unactive
5              new     active   unactive  ...   unactive   unactive   unactive[5 rows x 18 columns]Process finished with exit code 0

每月不同活跃用户的计数

#每月不同活跃用户的计数
purchase_status_ct=pivoted_status.replace('unreg',np.NaN).apply(lambda x: pd.value_counts(x))
print(purchase_status_ct)

输出结果:统计每个月客户活跃度的汇总

5 rows x 18 columns]
month     1997-01-01  1997-02-01  ...  1998-05-01  1998-06-01
active           NaN      1157.0  ...       459.0       446.0
new           7846.0      8476.0  ...         NaN         NaN
return           NaN         NaN  ...      1029.0      1060.0
unactive         NaN      6689.0  ...     22082.0     22064.0
purchase_status_ct.fillna(0,inplace=True)
# 浮点数转换为整数
purchase_status_ct.astype(np.int)
# 绘面积图 (purchase_status_ct要求一下转置矩阵)
purchase_status_ct.T.plot(kind='area')
plt.show()

每月不同活跃用户占比

消费用户构成:活跃+新增+回流

#每月不同活跃用户占比
Fdf=purchase_status_ct.T.apply(lambda x:x/x.sum(),axis=1)
print(Fdf.head())

 输出结果

             active       new    return  unactive
month                                             
1997-01-01  0.000000  1.000000  0.000000  0.000000
1997-02-01  0.070886  0.519299  0.000000  0.409815
1997-03-01  0.071319  0.307510  0.025244  0.595927
1997-04-01  0.075223  0.000000  0.044506  0.880272
1997-05-01  0.036148  0.000000  0.057785  0.906067

 分析

由上表可以看到每月用户的消费状态变化。

1. 活跃用户,持续消费用户对应的是---消费运营质量

2. 回流用户(上月不消费本月消费)对应的是---唤回运营情况;

3. 不活跃的用户对应的是---用户流失情况。

得出分析:流失用户增加,回流客户正在减少

5.6. 用户分层七:用户购买周期(按订单)

# 将用户分组后,每个用户的订单购买时间进行错位相减  shift():下一行减上一行的值
order_diff=group_user.apply(lambda x:x.order_dt-x.order_dt.shift())
print(order_diff.head())

 输出结果

user_id   
1        0       NaT
2        1       NaT2    0 days
3        3       NaT4   87 days
Name: order_dt, dtype: timedelta64[ns]Process finished with exit code 0

分析

1. 可以看到:user_id 1为空值,说明用户只购买过一个订单

2. user_id 2 的用户第一笔订单与第二笔订单在同一天购买

用户消费周期分布

#用户消费周期分布
(order_diff/np.timedelta64(1,'D')).hist(bins=20)
plt.show()

 

 

 分析

订单周期呈指数分布,用户的平均购买周期是68天,绝大部分用户的购买周期都低于100天。

用户生命周期(第一笔订单时间 & 最后一笔订单时间)

user_life=group_user['order_dt'].agg(['min','max'])
print(user_life.head())

输出结果

               min        max
user_id                      
1       1997-01-01 1997-01-01
2       1997-01-12 1997-01-12
3       1997-01-02 1998-05-28
4       1997-01-01 1997-12-12
5       1997-01-01 1998-01-03Process finished with exit code 0

相隔天数

user_life['life_period']=user_life['max']-user_life['min']
print(user_life.head())

得出结果

               min        max life_period
user_id                                  
1       1997-01-01 1997-01-01      0 days
2       1997-01-12 1997-01-12      0 days
3       1997-01-02 1998-05-28    511 days
4       1997-01-01 1997-12-12    345 days
5       1997-01-01 1998-01-03    367 daysProcess finished with exit code 0

描述一下

print(user_life['life_period'].describe())

输出结果

count                          23570
mean     134 days 20:55:36.987696224
std      180 days 13:46:43.039788104
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
Name: life_period, dtype: objectProcess finished with exit code 0

分析

可以看到,数据偏移较大,中位数是0天,意味着超过50%的用户生命周期是0天,即只购买了1次。

(user_life['life_period'] / np.timedelta64(1,'D')).plot(kind='hist',bins=40)
plt.show()

 分析:

可以看出,用户生命周期受只购买一次的用户影响比较大(因此可以排除生命周期为0天的用户再观察)

# 用户生命周期大于0天的分布图
cond=(user_life['life_period'] / np.timedelta64(1,'D'))
cond[cond>0].hist(bins=40)
plt.show()

分析

1. 有不少用户生命周期靠拢在0天,部分质量差的用户虽然消费了两次,但是仍然无法持续, 用户首次消费30天以内应该尽量引导;

2. 少部分用户集中在50-300天,属于普通型的生命周期;

3. 高质量用户的生命周期,集中在400天以后,这属于忠诚用户。

6. 复购率和回购率的分析

复购率:自然月内,购买多次的用户占比

回购率:曾经购买过的用户在某一时期内的再次购买占比

applymap()针对DataFrame里的所有数据。使用lambda函数,因为设计了多个结果,所以要用两个if else

user_id                                      ...                                    
1               0.0         NaN         NaN  ...         NaN         NaN         NaN
2               1.0         NaN         NaN  ...         NaN         NaN         NaN
3               0.0         NaN         0.0  ...         NaN         0.0         NaN
4               1.0         NaN         NaN  ...         NaN         NaN         NaN
5               1.0         0.0         NaN  ...         NaN         NaN         NaN[5 rows x 18 columns]Process finished with exit code 0

复购率

(purchase_r.sum()/purchase_r.count()).plot(figsize=(10,4))
plt.show()

 分析

1. 用sum和count相除即可计算出复购率。这两个函数都会忽略掉NaN,而NaN是没有消费的用户,count不论是0或1都会统计, 所以是总的消费用户数。而sum求和计算了消费两次及以上的用户。这里比较巧妙的用了替代法计算复购率。sql中也可以用。

2. 图上可以看出复购率在早期,因为大量新用户加入的关系,新客的复购率并不高,譬如1月新客们的复购率只有6%左右。 而在后期,这时的用户都是大浪淘沙剩下的老客户,复购率比较稳定,在20%左右。单看新客和老客,复购率有三倍左右的差距。

回购率:回购率是某一个时间窗口内消费的用户,在下个时间窗口仍旧消费的占比。

# 消费金额进行透视pivoted_amount = df.pivot_table(index='user_id',columns='month',values='order_amount',aggfunc='mean')
pivoted_amount.fillna(0,inplace=True)
columns_month = df['month'].sort_values().astype('str').unique()
pivoted_amount.columns = columns_month# pivoted_amount.head()
print(pivoted_amount.head())
         1997-01-01  1997-02-01  1997-03-01  ...  1998-04-01  1998-05-01  1998-06-01
user_id                                      ...                                    
1             11.77         0.0        0.00  ...         0.0        0.00         0.0
2             44.50         0.0        0.00  ...         0.0        0.00         0.0
3             20.76         0.0       20.76  ...         0.0       16.99         0.0
4             29.53         0.0        0.00  ...         0.0        0.00         0.0
5             21.65        38.9        0.00  ...         0.0        0.00         0.0[5 rows x 18 columns]Process finished with exit code 0
pivoted_purchase = pivoted_amount.applymap(lambda x : 1 if x>0 else 0)
print(pivoted_purchase.head())

输出结果

         1997-01-01  1997-02-01  1997-03-01  ...  1998-04-01  1998-05-01  1998-06-01
user_id                                      ...                                    
1                 1           0           0  ...           0           0           0
2                 1           0           0  ...           0           0           0
3                 1           0           1  ...           0           1           0
4                 1           0           0  ...           0           0           0
5                 1           1           0  ...           0           0           0[5 rows x 18 columns]Process finished with exit code 0
# 0代表当月消费过次月没有消费过,1代表当月消费过次月依然消费def purchase_return(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)return pd.Series(status, index = pivoted_purchase.columns)pivoted_purchase_return = pivoted_purchase.apply(purchase_return,axis = 1)print(pivoted_purchase_return.head())
         1997-01-01  1997-02-01  1997-03-01  ...  1998-04-01  1998-05-01  1998-06-01
user_id                                      ...                                    
1               0.0         NaN         NaN  ...         NaN         NaN         NaN
2               0.0         NaN         NaN  ...         NaN         NaN         NaN
3               0.0         NaN         1.0  ...         NaN         0.0         NaN
4               0.0         NaN         NaN  ...         NaN         NaN         NaN
5               1.0         0.0         NaN  ...         NaN         NaN         NaN[5 rows x 18 columns]Process finished with exit code 0
# 回购率,计算方法和复购率类似,同样的逻辑
(pivoted_purchase_return.sum()/pivoted_purchase_return.count()).plot(figsize=(10,4))
plt.show()

 分析:

1. 从上图看出,用户的回购率高于复购率,约在30%左右,和老客户差异不大。

2. 从回购率和复购率综合分析,新客的整体质量低于老客,老客的忠诚度(回购率)很好,消费频次稍次

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘市场热销的4款问卷调查工具

当谈到进行在线问卷调查时&#xff0c;选择正确的工具可以使调查过程完全不同。市场上有这么多可供选择的产品&#xff0c;要找到一款符合我们需求的工具不是一件容易的事儿。在本文中&#xff0c;小编将和大家一起讨论4款市面上好用的问卷调查工具盘点&#xff0c;并比较它们的…

关于满意度调查问卷数据处理1-基于处理工具SPSS和EXCEL

1、从后台系统导出问卷数据后&#xff0c;通过Excel对初始数据进行清洗。&#xff08;这里注意一个细节&#xff0c;如果导出的数据属于文本数据则在Excel里边将其转化为数值型&#xff0c;在导入SPSS软件中时可以减少对变量视图界面的类型或者其他的手动处理。&#xff09; …

武大邮箱无法收到github发来的邮件

武大邮箱无法收到github发来的邮件 解决思路&#xff1a;将github设置为白名单 具体步骤如下&#xff1a; 1.点击头像 2.点击Setting 3.在add前面的那个框中输入 github.com 4.重新去github上发送邮件&#xff0c; Bingo!

英文期刊论文写作——通往国际学术舞台的阶梯期末考试】最后一题有参考

1.Thirty-two patients,——CT and MRI examinations were analyzed retrospectively. 2.According to a recent survey, 26% of all American adults, down from 38% thirty years ago, now smoke. This __________ can be partly attributed to the mounting evidence linki…

如何避免SCI写作中的中式思维以及无处不在的Chinglish

现在随着全球经济的下行&#xff0c;很多小伙伴都选择了延时就业&#xff0c;因此更多的人开始考研和考博。新东方大学生学习与发展中心发布的《新东方2023考研报告》预测&#xff1a;2023考研报名将超过520万人。俗话说&#xff08;我道听途说的&#xff09;&#xff1a;一入科…

英文科技论文写作与学术报告Lecture 2习题答案

英文科技论文写作与学术报告 Lecture 2习题 英文科技论文写作与学术报告 选择题 2.1选择题 2.2选择题 2.3 选择题 2.1 1-5 DCABD 选择题 2.2 1-7 CCABACD 选择题 2.3 1-7 CCBABDC 第二章完毕

孩子跟妈妈一起去按摩

孩他妈找了一个按摩的地方&#xff0c;办了一个金卡。孩子经常生病也带去一起按摩。 听孩他妈说按摩师很喜欢他&#xff0c;他与按摩师老太太混的很熟。 今天回来&#xff0c;要给我示范下怎么给他按摩。 他先抓起我一只手&#xff0c;按手指肚&#xff0c;中间还带有抹粉的…

促进早期的父母-婴儿情感联系可以改善早产儿的皮质网络

在早期大脑发育期间&#xff0c;如果暴露在环境逆境中&#xff0c;如早产&#xff0c;会影响早期大脑组织发育。在这里&#xff0c;我们研究了通过促进母婴情感连接的多模态环境富集是否可以改善早产儿皮质活动网络的发育。我们使用高密度脑电图记录参加家庭养育干预(FNI)随机对…

(转)一个真实的幼升小故事 女儿的上学辛酸史

1.100比37大 朋友的孩子上的是个一级一类幼儿园&#xff0c;我那朋友工作挺忙的&#xff0c;想着幼儿园还不错&#xff0c;孩子也挺高兴的&#xff0c;不用操什么心&#xff0c;3年就过来了。到该上小学的时候&#xff0c;因为朋友单 位附近就有一个顶级名校小学&#xff0c;所…

7旬夫妻为3岁女儿庆生

7旬夫妻为3岁女儿庆生#在全社会提倡生育的时候&#xff0c;这样的新闻特别励志&#xff0c;70岁的人可以生孩子。为什么年轻人不主动多生孩子&#xff1f;我们应该向这两位老人学习&#xff01; 刚生下这个孩子的时候&#xff0c;我很担心两位老人会被罚款&#xff0c;甚至受到…

8岁的小女孩

英文关键词:Hello, can you imagine an 8-year-old girl wearing a pink dress, leaking shoulders, not defining herself by worldly standards, this is a valuable quality. --creative ,beautiful scene,cinematic shot, --ar 9:16 --test --creative,, 8K, Hyperrealism…

Checkra1n越狱更新0.12.4版本,支持iOS14.7.1越狱

checkra1n越狱团队更新发布0.12.4版本。 新版本支持iOS 14.7.1越狱&#xff08;5S~X)(A7~A11) Bug修复&#xff1a; 修复了A9X设备IOS14.5在0.12.3上越狱不跑代码问题 工具下载地址&#xff1a; QQ群&#xff1a;1群 65044698 2群 585836900 3群 47735801 工具使用教程&…

『0001』 - 如何通过 MyEtherWallet 创建钱包以及如何通过 Ethereum Wallet 和 MetaMask 恢复钱包账号

视频教程 来源&#xff1a; 黎跃春区块链博客 学习目标 钱包介绍创建钱包发送和接收以太币恢复钱包如何获取以太币 钱包介绍 Ethereum Wallet 钱包 开启Ethereum智能合约开发(Smart Contract)最快的方式就是Ethereum Wallet&#xff0c;它支持Windows, MacOSX 和 Linux开发…

一文读懂 WalletConnect

文章概览 WalletConnect 能干什么 WalletConnect 的市场支持情况 WalletConnect 消息通讯工作原理 WalletConnect 消息安全如何保障 WalletConnect 如何快速接入推送 01 WalletConnect 能干什么 它是⼀个基于⼆维码建立连接的基础通讯设施。你可以在它的基础上去建⽴各…

WALLET 通证减半:早期用户分配将降至 4%

WALLET 通证即将满 1 年&#xff0c;这意味着根据 Ambire 钱包白皮书&#xff0c;它的年度早期用户供应量将削减至 4%&#xff0c;随着应用率的增长&#xff0c;通货膨胀率将大幅降低。 WALLET 一周年 根据官方消息&#xff0c;WALLET 通证的生成&#xff08;token generation …

如何在Coinbase Wallet 直接使用HT5?

最新分享‼️‼️ 现在跟着以下步骤 就可以在Coinbase Wallet直接使用 HT5 啰 App Store / Google Play 商城下载注册&#xff0c;&#x1f4f2;点击此链接 STEP1 商城下载Coinbase Wallet (可点击上方链接进入商城) STEP2 请先注册您的个人钱包 S…

如何通过UTON WALLET数字钱包创建和使用你的元宇宙身份

最近很多玩家登录UTONMOS APP的时候&#xff0c;发现多了一个「数字钱包登录」。 数字钱包&#xff1f;这是什么&#xff1f; 随着科技创新和数字经济的不断发展&#xff0c;我们正在从信息互联网步入价值互联网&#xff0c;越来越多的人意识到数据和隐私安全的重要性。此时&a…

0.5mm的焊锡丝能吃多大电流_BTB/FPC大电流弹片微针模组高度满足FPC连接器测试需求...

FPC连接器的市场发展前景广阔&#xff0c;小而薄的外形结构&#xff0c;有着高频信号的传输功能&#xff0c;pitch值也由0.5mm向着0.3mm甚至更小的pitch值进化。5G手机产量的高速增长将会带动FPC连接器的大量增长。FPC连接器的组成部分有胶芯、舌片、端子、焊接片&#xff0c;组…

0.5mm的焊锡丝能吃多大电流_3C锂电池测试:大电流弹片微针模组与pogopin探针模组的优劣势对比...

锂电池具有高能量密度、高电压、寿命长、无记忆效应等优点&#xff0c;是21世纪发展的理想电源。锂电池可广泛应用于 3C 领域&#xff0c;比如手机、平板电脑、笔记本电脑、可穿戴式设备等&#xff0c;因而也被称为3C锂电池。由于3C锂电池易因短路、过充等原因导致烧毁或爆炸&a…

0.5mm的焊锡丝能吃多大电流_智能手机测试中大电流弹片微针模组的应用与优势...

智能手机重要的三个组成部分就是电池、屏幕和摄像头&#xff0c;属于手机的硬件。智能手机组装硬件组装前&#xff0c;通常需要先进行测试&#xff0c;确保性能和质量是否达到出厂的合格标准。在智能手机电池、 屏幕&#xff08;LCD屏幕/OLED屏幕&#xff09;、摄像头测试中&am…