CD店铺消费者消费数据分析

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
  • 首先当然要把该import的都全部Import进来。

plt.rcParams['font.family'] = ['Arial Unicode MS'] 
  • 为了待会儿画图正常显示中文。因为我是MAC系统,所以代码跟WIN的可能有些不同。

pd.__version__
  • 我pd的版本,是最新安装的,0.24.0

columns=['user_id','order_dt','order_products','order_amount']
df = pd.read_csv('CDNOW_master.txt',names=columns,sep='\s+')
#如果数据本身以空格做分割的话,这里sep要用\s+
  • 导入数据,并把列头分别命名为:'user_id','order_dt','order_products','order_amount'

df.order_dt=pd.to_datetime(df.order_dt,format='%Y%m%d')
  • 由于原数据时间那一项是‘19970101’这样的形式的,因此要用pd.to_datetime()把格式换成yyyy-mm-dd的格式,进行后续的分析时才更加方便。

df['month']=df.order_dt.values.astype('datetime64[M]')
#后续要解决的问题都需要以月为单位来计算,因此要多加一条column:"month",以月为单位。

df.head(10)
CD店铺消费者消费数据分析_第1张图片
  • 看下表头前十行大概长啥样。

df.describe()
CD店铺消费者消费数据分析_第2张图片
  • 先给这些数据做一些简单的统计分析。可以看出:大部分订单只消费了少量商品(平均2.4),用户的消费金额比较稳定,平均消费35元,中位数25元。有一定的极值干扰。



接下来就开始进行进一步的分析。

首先:1.进行用户按月消费趋势的分析。分别有:

  • (1)每月消费的总金额
  • (2)每月的消费次数
  • (3)每月的产品购买数
  • (4)每月的消费人数
grouped_month=df.groupby('month') 
  • 由于是按月消费的分析,因此要按月分组。

grouped_month.order_amount.sum().plot()#(1)每月消费的总金额
  • 利用.sum()函数把order_amount那一列按月分组的总和求出来,并且画图,得到下列图片:
CD店铺消费者消费数据分析_第3张图片

grouped_month.order_products.count().plot()#(2)每月的消费次数
  • 利用.count()函数把总消费次数按月分组的总和求出来(这里用order_products或者order_amount其实都一样)。画图,并且得到下列图片:
CD店铺消费者消费数据分析_第4张图片

grouped_month.order_products.sum().plot()#(3)每月的产品购买数
  • 每月产品总购买数的画图:
CD店铺消费者消费数据分析_第5张图片

grouped_month.user_id.count().plot()#(4)每月消费人数
  • 每月消费人数的画图:
CD店铺消费者消费数据分析_第6张图片

  • 由以上四图可知,每月消费的总金额、消费次数、产品购买数以及消费人数,都在前三个月上升达到高峰,随后在3到4月份时巨幅下降,4月份之后开始稳定上下波动,甚至有轻微下降趋势。



2.用户个体消费分析

  • (1)用户消费金额、产品购买数的描述统计
  • (2)用户消费金额和产品购买数的散点图
  • (3)用户消费金额的分布图
  • (4)用户产品购买数的分布图
  • (5)用户累计消费金额占比(百分之多少的用户占了百分之多少的消费额

grouped_user=df.groupby("user_id")
  • 用户个体消费分析,就要根据user_id来分组了。

grouped_user.sum().describe() #(1)用户消费金额、产品购买数的描述统计。
CD店铺消费者消费数据分析_第7张图片
  • 由上表可知:
  • ①用户平均每个人购买7张CD,但中位数是3,说明有小部分用户购买了大量CD。
  • ②用户平均消费106元,中位值有43,判断同上,有极值干扰。

  • 由于散点图对极值比较敏感,可以做简单的过滤,因此:
grouped_user.sum().plot.scatter(x='order_amount',y='order_products',c='b')
  • 因此可得:
CD店铺消费者消费数据分析_第8张图片
  • 由上图可知,数据主要集中在order_amount小于3000,order_products小于200。因此超出这两个范围的都视为极值。

grouped_user.sum().query('order_amount<3000').query('order_products<200').plot.scatter(x='order_amount',y='order_products',c='b')
(2)用户消费金额和产品购买数的散点图
  • 再缩小范围做一幅图,可以更加清晰地看到,绝大部分的数据集中在order_amount小于1000,order_products小于100。:
CD店铺消费者消费数据分析_第9张图片

  • 用户消费金额的分布图
grouped_user.sum().query('order_amount<1000').order_amount.plot.hist(bins=50)
#(3)用户消费金额的分布图(根据上面散点图,选择数据较为集中的部分进行分析。)
CD店铺消费者消费数据分析_第10张图片

  • 用户消费产品数的分布图
grouped_user.sum().query('order_products<100').order_products.plot.hist(bins=50)
#(4)用户消费产品数的分布图(根据上面散点图,选择数据较为集中的部分进行分析)
CD店铺消费者消费数据分析_第11张图片

  • 用户累计消费金额占比:利用cumsum() 计算轴向元素累加和,再除以sum,得到累计比例。
user_cumsum=grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())

user_cumsum.reset_index().order_amount.plot()
CD店铺消费者消费数据分析_第12张图片
  • 按用户消费金额进行升序排列,由图可知,排名前50%的用户只贡献了15%左右的消费额度。而排名最后3570的用户就贡献了60%的消费额度。



3.用户消费行为:

  • (1)用户第一次消费(首购)
  • (2)用户最后一次消费
  • (3)新老客户消费比:
    • ① 多少用户仅消费了一次?② 每月新客占比。
  • (4)用户分层:
    • ① RFM。② 新、活跃、回流、流失。
  • (5)用户购买周期(按订单)
    • ① 用户消费周期描述。② 用户消费周期分布。
  • (6)用户生命周期(按第一次&最后一次消费)
    • ① 用户生命周期描述。② 用户生命周期分布。

  • (1)用户第一次消费(首购):
grouped_user.min().order_dt.value_counts().plot(figsize=(10,4))
#第一次购买的时间,就是时间最小,所以用.min()。然后用value_counts()汇总起来。 
CD店铺消费者消费数据分析_第13张图片
  • 由图可知,所有用户的首购都集中在97年1月1日至97年3月29日,2月上旬以前首购客户数量一直稳定上升。在2月10日左右首购客户的数量产生剧烈波动,在2月下旬开始稳定,然后一直到3月下旬都呈现稳定下跌的状态。

  • (2)用户最后一次消费:
grouped_user.max().order_dt.value_counts().plot()
#最后一次消费,日期最大。
CD店铺消费者消费数据分析_第14张图片
  • 用户最后一次购买的分布比第一次分布广,大部分最后一次购买集中在前三个月,说明有很多用户购买了第一次之后就不再购买了。而且随着时间的递增,最后一次购买也在递增,说明消费呈现流失上升的状况。

  • (3)新老客户比:
    • ① 有多少客户只消费了一次?
      用count对grouped_user的order_dt进行统计,=1的就是只消费一次客户。
(grouped_user.order_dt.count()==1).value_counts()
CD店铺消费者消费数据分析_第15张图片
  • 接近一半的客户是只消费了一次的。

  • ② 每月新客占比。
user_life=grouped_user.order_dt.agg(['min']).sort_values('min')
user_life['month']=user_life['min'].values.astype('datetime64[M]')
  • 新建一个dataframe,user_life,以min为首购日期。在user_life那里添加一列month,也是首购日期,不过是以月为单位。
user_life.groupby('month').month.describe()
CD店铺消费者消费数据分析_第16张图片
  • 由上表可知每个月份的首购客户数量:
    1月份新客占比:7846/(7846+8476+7248)=33.29%
    2月份新客占比:8476/(7846+8476+7248)=35.96%
    3月份新客占比:7248/(7846+8476+7248)=30.75%

  • (4)用户分层:
    ①RFM模型分析(最近一次消费、消费频率、消费金额)。
rfm=df.pivot_table(index='user_id',
                          values=['order_products','order_amount','order_dt'],
                          aggfunc={'order_dt':'max',
                                  'order_amount':'sum',
                                  'order_products':'count'})
rfm.head()

利用透视表功能,把user_id作为索引,根据order_amount和order_dt的值,算出每个用户最大购买日期(最后一次消费的日期)、总消费金额,以及总消费次数(这里用 'order_products':'count' 或者 'order_amout':'count'都一样,因为算的是次数而不是购买的产品数。每次消费买的产品数都可能不一样。)然后我们可以看下rfm表大概长啥样:


CD店铺消费者消费数据分析_第17张图片

rfm["R"]=(rfm.order_dt.max()-rfm.order_dt)/np.timedelta64(1,'D')
  • R,Recency,计算最近一次消费距离至今多少天(因为数据比较久远,所以用order_dt里面最大的一项作为今天)
rfm=rfm.rename(columns={'order_products':'F','order_amount':'M'})
  • F,Frequency,消费频率,这里为总消费次数;M,Monetary,为总金额。

  • 然后把按照r、f、m这三个维度取平均,每个维度都把高于平均值的标记为1,低于平均值得标记为0.
    • 这样就有以下8种用户:
      111 重要价值客户
      011 重要保持客户
      101 重要挽留客户
      001 重要发展客户
      110 一般价值客户
      010 一般保持客户
      100 一般挽留客户
      000 一般发展客户
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' : '重要挽留客户',         
         '110' : '一般价值客户',
         '001' : '重要发展客户',
         '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添加一列客户标示。
rfm.head(10)
CD店铺消费者消费数据分析_第18张图片

rfm_grouped=rfm.groupby('label') 
rfm_grouped.sum()
CD店铺消费者消费数据分析_第19张图片
  • 可以看到不同维度客户的占比

pd.Series(rfm_grouped['label'].count(),name='series')
CD店铺消费者消费数据分析_第20张图片
  • 可以看到不同客户的总数。
pd.Series(rfm_grouped['label'].count(),name='series').plot.pie()
CD店铺消费者消费数据分析_第21张图片
  • 画成饼图更加直观。
  • 从RFM分层可知,本数据集的大部分用户为一般挽留客户,其次是重要保持客户。

② 用户生命周期:新、活跃、回流、流失(不活跃)

  • 新:首次消费在最新时间。
  • 活跃:持续消费。
  • 回流:曾今有过消费,隔了超过一个月后再次消费。
  • 流失:曾今有过消费,到最新时间为止还没有消费过。
    本例直接按一个月作为间隔。
pivoted_counts = df.pivot_table(index='user_id', # 使用数据透视,将每个用户每月消费次数计算出来
                               columns='month', # 如果没有数据的话(比如1号客户1997年2月1日没有数据),数据透视功能也会把它变成NaN。
                               values='order_dt',# 因此要价格fillna(0)把空值变成0。
                               aggfunc='count').fillna(0)
pivoted_counts.head()
CD店铺消费者消费数据分析_第22张图片
  • 透视表大概长这个样子。
  • 由于本次案例是需要计算每个月是否有消费,具体消费多少次不重要,因此可以把大于0的都当做1:
purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
  • 由于很多的首次消费是在2月或者3月,所以在写函数判断的时候需要考虑在内,并不是所有的首次消费都在一月:
def active_status(data):
    status=[]
    for i in range(18): #共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')
                    
    return status

函数的逻辑:

若本月没有消费:
  • 若之前是未注册,则依旧为未注册。
  • 若之前有消费,则为流失。
  • 其他情况,视为未注册。
若本月有消费:
  • 若是第一次消费,则是新用户。
  • 如果之前有过消费,且上个月为不活跃,则为回流。
  • 如果上个月为未注册,则为新用户。
  • 除此之外,为活跃。
indexs=df['month'].sort_values().astype('str').unique()
purchase_sta=purchase.apply(lambda x:pd.Series(active_status(x),index=indexs),axis=1)
purchase_sta.head()
CD店铺消费者消费数据分析_第23张图片
  • 可得到一张不同用户在不同月份的不同状态(new=新、active=活跃、return=回流、unactive=流失),unreg相当于未注册,指这个用户在这个月及以前从未购买过产品,主要为了统计起来更加方便而加进去。
purchase_sta.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x)).fillna(0).T
  • 把unreg替换成NaN,再用fillna(0)把空值填为0。然后转置,把月份作为索引行,状态作为列,得到如下的表:
CD店铺消费者消费数据分析_第24张图片
purchase_sta.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x)).fillna(0).T.plot.area(figsize=(10,4))
  • 作出非堆积效果图:
CD店铺消费者消费数据分析_第25张图片
  • 由图可知,到了在前三个月,新用户增加的数量非常大。从三月一号开始,用户开始快速流失。到后面的几个月流失用户基本占绝大比例。

(5)用户购买周期(按订单)
  • 用户消费周期描述
  • 用户消费周期分布
order_diff=grouped_user.apply(lambda x:x.order_dt-x.order_dt.shift())
  • 算出不同用户每次消费相隔多少时间
order_diff.describe()
CD店铺消费者消费数据分析_第26张图片
  • 可以看到每次消费相隔时间大致的分布。
(order_diff/np.timedelta64(1,'D')).hist(bins=20)
  • 把分布图作出来:
CD店铺消费者消费数据分析_第27张图片
  • 由上图以及描述可知:

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


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

① 用户消费周期描述

(user_life['max']-user_life['min']).describe()
CD店铺消费者消费数据分析_第28张图片

② 用户消费周期分布

((user_life['max']-user_life['min'])/np.timedelta64(1,'D')).hist(bins=40)
CD店铺消费者消费数据分析_第29张图片



4.复购率和回购率分析

  • (1) 复购率(自然月内,购买多次的用户占比)
  • (2)回购率(曾经购买过的用户在某一时期内的再次购买的占比)
  • (1)复购率:当月多次购买(超过一次)
purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x == 0 else 0)
  • "1"表示消费次数大于1;"0"表示只消费过一次;"NaN"表示没买过,在.count中就不会计算在名额内。求复购率就计算消费次数大于1的占比就行了。
(purchase_r.sum()/purchase_r.count()).plot(figsize=(10,4))
CD店铺消费者消费数据分析_第30张图片
  • 由上图可知,复购率在前三个月高速增长,最终在大概四月份的时候稳定在20%左右。

  • (2) 回购率:上个月有过消费,这个月又有消费,就叫回购。
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) 
    return status  
purchase_b=purchase.apply(lambda x:pd.Series(purchase_back(x),index=indexs),axis=1)
purchase_b.head()
CD店铺消费者消费数据分析_第31张图片
  • 1代表本月有消费,下个月也有消费;0代表本月有消费,但是下个月没有消费;NaN代表本月没有消费。
(purchase_b.sum()/purchase_b.count()).plot(figsize=(10,4))
  • 本月与次月都有消费的 / 本月有消费的,就是回购率。
CD店铺消费者消费数据分析_第32张图片
  • 可以看出,回购率在前三个月快速增长,知道四月份增长到30%以后,一直维持在30%左右波动。

你可能感兴趣的:(CD店铺消费者消费数据分析)