某CD销售网站用户消费情况分析

作者: 米兔妮妮 | 来源:发表于2019-02-17 17:34 被阅读70次

    目录

    前言

    一. 数据预处理

    1.1 数据导入
    1.2 数据清洗

    二. 月用户消费趋势分析

    2.1 每月消费总金额
    2.2 每月订单总数
    2.3 每月消费总产品数
    2.4 每月消费人数
    2.5 每月用户平均消费金额
    2.6 每月用户平均消费次数

    三. 用户个体消费分析

    3.1 用户消费金额和次数的散点图
    3.2 用户消费金额的分布图
    3.3 用户消费次数的分布图
    3.4 用户累计消费金额占比

    四. 用户消费行为分析

    4.1 用户第一次消费(首购)
    4.2 用户最近一次消费
    4.3 新老客消费比
    4.4 用户分层

    前言

    1、写这篇报告的目的主要是为了练手,熟悉数据分析的流程,把前期学的python数据分析库等理论知识应用到实际项目中,加深对理论知识的掌握度。
    2、数据来源于CDNow网站,为用户购买CD的消费明细。

    一. 数据预处理

    先查看一下原始数据: 原始数据

    每一行代表一个用户订单的购买明细,共有用户编号、购买日期、购买产品数量、订单消费金额四个字段。但是原始数据中没有包含表头,我们导入数据时需要添加表头。

    1. 数据导入

    import numpy as np  
    import pandas as pd
    columns = [ 'user_id', 'order_dt', 'order_products', 'order_amount' ]  # 定义表头
    df = pd.read_table('CDNOW_master.txt', names=columns, sep='\s+')   # 分隔符为多个空格
    

    此处注意原始数据使用空白符分割,需要指定分隔符,\s+代表任意多个空白符。
    观察数据样本:

    df.head()
    
    订单数据样本

    查看数据类型信息,观察数据是否被正确识别:

    df.info()
    
    数据类型信息

    发现购买日期order_dt为整数类型,需要进行数据清洗,将其转换为日期类型。 没有空值,不需要填补缺失值。

    查看整体统计信息:

    df.describe()
    
    描述性统计信息
    • 大部分订单只购买了少量商品(平均2.4),50%的订单购买商品数量了在2个及以下,75%的订单购买商品数量在3个及以下,最多的订单购买了99个商品,平均消费商品数量存在一定极值干扰;
    • 订单平均交易金额35元,中位数在25元,75%的订单金额在43元及以下,订单最大金额为1286,有一定极值干扰。

    2. 数据清洗——类型转化

    将刚刚提到的购买日期order_dt转化为时间类型:

    df.order_dt = pd.to_datetime(df.order_dt, format='%Y%m%d')
    
    再次查看数据信息: 类型修改后数据信息

    order_dt成功转化为时间类型。

    二. 月用户消费趋势分析

    因为是按月分析,所以新增一个月份字段并查看数据样本:

    df['month'] = df.order_dt.values.astype('datetime64[M]')
    df.head()
    
    增加月份后的数据样本

    可以看到month精确到了月份,后面的日都变成了1号。然后按月分组数据:

    grouped_month = df.groupby('month')
    

    2.1 每月消费总金额

    order_amount_month = grouped_month.order_amount.sum()
    # 或者order_amount_month = grouped_month[['order_amount']].agg(['sum'])  
    order_amount_month.head()
    
    每月消费总金额抽样

    可视化每月消费总金额情况:

    import matplotlib.pyplot as pet
    %matplotlib inline
    
    plt.style.use('ggplot')  # 使用设计风格ggplot
    order_amount_month.plot()
    
    每月消费总金额变化情况

    消费金额在前三个月达到最高峰,之后急剧下降,1997年4月份之后每月消费总金额比较平稳,有轻微下降趋势。

    2.2 每月订单总数

    grouped_month.user_id.count().plot()
    
    每月订单总量变化情况

    前三个月订单总数量平均为10000笔左右,后续月份平均每个月的订单量在2500笔左右。

    2.3 每月消费总产品数

    grouped_month.order_products.sum().plot()
    
    每月消费产品数量变化情况

    前三个月消费总产品数达到最高峰,平均为24000左右,后续月份平均每月消费产品量约在6000左右。
    2.1、2.2、2.3的结果也可以通过透视图获得:

    pt = df.pivot_table(index = 'month',
                  values = [ 'order_products', 'order_amount', 'user_id' ],
                  aggfunc = {'order_products' : 'sum',
                            'order_amount' : 'sum',
                            'user_id' : 'count'})
    pt.order_amount.plot()
    pt.order_products.plot()
    pt.user_id.plot()
    

    2.4 每月消费人数

    同一个月中一个用户可能消费多次,需要去除掉重复的user_id。
    方法一

    grouped_month.user_id.nunique().plot()
    

    方法二

    grouped_month.user_id.apply(lambda x : len( x.drop_duplicates() ) ).plot()  # 同一个月中一个用户可能消费多次,需要去除掉重复的user_id
    

    方法三:

    df.groupby([ 'month', 'user_id']).count().reset_index().groupby('month').user_id.count().plot()  # 先按照月份和用户ID分组达到对用户ID去重的目的
    
    每月消费人数变化情况
    • 每月消费人数低于每月订单总数(即每月消费次数),但差异不大;
    • 前三个月每月的消费人数在8000-10000人左右,后续月份平均消费人数不足2000。

    2.5 每月用户平均消费金额

    # 每月用户平均消费金额 = 总金额 /  每月消费总人数
    grouped_month.apply( lambda x : x.order_amount.sum() / x.user_id.nunique() ).plot()
    
    月用户平均消费金额变化趋势

    前三个月平均金额稍低,后续月份每月用户平均消费金额在47-57之间波动,变化不大。

    2.6 每月用户平均消费次数

    # 每月用户平均消费次数 = 每月订单总量 / 每月消费总人数
    grouped_month.apply( lambda x : x.user_id.count() / x.user_id.nunique() ).plot()
    
    月用户平均消费频次变化趋势
    • 每月用户平均消费频次在1.13-1.15之间,前三个月由于用户大量涌入,部分用户可能仅消费了一次,导致频次略低;
    • 后续月份用户平均消费频次比较平稳,且略高于前3个月。

    三. 用户个体消费分析

    观察用户消费金额、购买产品数量的描述统计:

    grouped_user = df.groupby('user_id')
    grouped_user.sum().describe()
    
    用户消费金额及购买产品数量的描述性统计
    • 平均每用户购买了7张CD,但是中位数只有3,说明小部分用户购买了大量CD;
    • 用户平均消费106元,中位值为43,75%分位数为106,刚好等于平均消费,有25%的用户消费的比平均金额多,再看最大消费金额为13990(CD狂热爱好者啊),佐证了上面小部分用户购买了大量CD的结论,数据存在极值干扰。

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

    grouped_user.sum().plot.scatter(x = 'order_products', y = 'order_amount' )
    
    用户消费数量和消费金额的关系图1

    可以看到最后面两个极值的存在拉大了图形区域,使得密集区域集中在左下角。通过过滤排除极值干扰:

    grouped_user.sum().query('order_products < 350').plot.scatter(x = 'order_products', y = 'order_amount')
    
    用户消费数量和消费金额的关系图2

    散点图呈现明显的线性关系,可以推测CD产品比较单一,单价比较稳定。

    3.2 用户消费金额的分布图

    grouped_user.sum().order_amount.plot.hist(bins = 100)
    plt.xlabel('order_amount')  # 设置x轴的名称
    
    用户消费金额分布情况
    从直方图可知,用户消费金额,绝大部分呈现集中趋势,大部分用户消费金额在1500以内,小部分异常值干扰了判断。
    使用切比雪夫定律(95%的数据位于其平均值+5标准差范围之内)过滤异常值,由3.1的用户消费金额及购买产品数量的描述性统计可知,95%的用户消费金额位于106+5240=1306范围内:
    grouped_user.sum().query('order_amount < 1306').order_amount.plot.hist(bins = 20)
    
    过滤极值后的用户消费金额分布情况

    3.3 用户消费次数的分布图

    同上,获取过滤掉极值之后的用户购买产品数量分布:

    grouped_user.sum().query('order_products < 100').order_products.plot.hist(bins = 20)
    
    用户购买产品总数量分布情况

    可以看出,大部分用户仅购买了1-5张CD,整体购买数量和消费金额成指数下降趋势。

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

    user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x : x.cumsum() / x.sum())  # 对每一列应用apply里面的函数
    user_cumsum.reset_index().order_amount.plot()  # 重新设置索引方便作图,x轴为索引
    
    用户累计消费金额占比分布情况

    50%的用户仅贡献了约15%的消费额,消费金额排名靠前的20%用户贡献了60%的消费额。

    四. 用户消费行为分析

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

    备注:首购是一个比较重要的维度,它和渠道等息息相关, 尤其是客单价比较高用户留存率又比较低的行业, 可以通过首购分析第一次购买的用户渠道,然后拓展出运营的方式。
    通过对用户第一次购买时间最小值的统计获取用户首购时间分布情况:

    grouped_user.min().order_dt.value_counts().plot()
    
    用户首购时间分布情况

    用户第一次购买时间集中在前三个月,其中在2月中旬的时候有一次比较大的波动。

    4.2 用户最近一次消费

    grouped_user.max().order_dt.value_counts().plot()
    
    用户最后一次消费时间分布情况
    • 用户最后一次购买的分布比第一次分布广;
    • 大部分用户最后一次购买时间,集中在前三个月,说明很多用户购买了一次后就不再购买;
    • 随着时间的递增,最后一次购买数量也在递增,消费呈现流失上升的状况。

    4.3 新老客消费比

    4.3.1 多少用户仅消费了一次

    求出用户的购买时间的最大值和最小值,若相等,说明用户仅消费了一次:

    user_life = grouped_user.order_dt.agg(['min', 'max'])
    user_life.head()
    
    用户首购和最近一次购买情况
    (user_life['min'] == user_life['max']).value_counts()
    
    用户是否仅消费了一次

    超过一半的用户,仅消费了一次。

    4.3.2 每月新客占比

    grouped_month_user = df.groupby(['month', 'user_id'])  # 按月和用户ID分组
    tmp = grouped_month_user.order_dt.agg(['min']).join(grouped_user.order_dt.min())  # 求出用户在当月首购时间和用户在所有时间段的首购时间
    tmp['is_new'] = (tmp['min'] ==  tmp['order_dt'])  # 新增一列,是否首购时间在当月,即是否为新客
    tmp.reset_index().groupby('month').apply(lambda x : x.is_new.sum() / x.user_id.count() ).plot()  # 计算新客占比
    
    每月新客占比

    新客集中在前三个月,后面消费的均为老用户。

    4.4 用户分层

    R:最近一次消费时间
    F:消费频率
    M:消费金额
    通过透视表获取用户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()
    
    用户RFM相关维度情况抽样

    求出相应的R、F、M:

    rfm['R'] = (rfm.order_dt.max() - rfm.order_dt) /np.timedelta64(1, 'D') # 把所有用户order_dt的最大值作为现在的时间,求出距今天数
    rfm.rename(columns = {'order_products' : 'F', 'order_amount' : 'M'}, inplace = True)
    rfm.head()
    
    用户RFM情况抽样

    将用户在R、F、M三个维度上分为低于平均额度和高于平均额度的用户(划分标准根据不同业务设计不同):

    rfm[['R', 'F', 'M']].apply(lambda x : x - x.mean()).head() 
    
    用户RFM与平均值的比较情况

    给用户打标签:

    def rfm_label(x):  # 对每一行数据根据其rfm的值求出其label
        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_label, axis = 1)
    ram.head()
    
    用户标签情况抽样

    可以看到,用户已经都打上了相应的标签。

    rfm.groupby('label').sum()
    
    不同标签的用户R、F、M求和情况
    rfm.groupby('label').count()
    
    不同标签的用户R、F、M计数情况

    从RFM分层结果可知,“重要保持客户”为主要利润来源,即最后一次消费时间越晚,消费频次越高,消费额度越高的用户是优质客户。
    用不同颜色区分不同标签的用户:

    rfm.loc[ rfm.label == '重要保持客户', 'color'] = 'brown'
    rfm.loc[ rfm.label == '重要发展客户', 'color'] = 'grey'
    rfm.loc[ rfm.label == '重要价值客户', 'color'] = 'c'
    rfm.loc[ rfm.label == '重要挽留客户', 'color'] = 'r'
    rfm.loc[ rfm.label == '一般保持客户', 'color'] = 'k'
    rfm.loc[ rfm.label == '一般发展客户', 'color'] = 'y'
    rfm.loc[ rfm.label == '一般价值客户', 'color'] = 'm'
    rfm.loc[ rfm.label == '一般挽留客户', 'color'] = 'w'
    
    rfm.plot.scatter('F', 'R', c=rfm.color)
    
    不同标签的客户分布

    从图中可以看到大部分用户的购买频次在200以内,少部分的极值可能会对我们使用平均值划分RFM造成一定程度的偏差(平均值对大部分用户来说偏大),所以如果使用平均值划分应该考虑到先根据切比雪夫定律剔除极值。

    相关文章

      网友评论

        本文标题:某CD销售网站用户消费情况分析

        本文链接:https://www.haomeiwen.com/subject/lsfbeqtx.html