美文网首页数据蛙强化课程第一期
CD 网站上客户消费记录分析

CD 网站上客户消费记录分析

作者: 此我非彼我隆隆 | 来源:发表于2019-04-03 12:02 被阅读0次

    1 项目介绍

    • 项目名称:CD 网用户消费分析
    • 使用工具:jupyter notbook

    分析步骤及内容:

    • 1. 数据预处理——数据的清洗
      缺失值的处理、数据类型的转化
    • 2. 用户消费趋势的分析
      从每月的消费总金额、每月的消费次数、每月的产品购买量、每月的消费人数四个维度上进行分析
    • 3. 用户个体消费数据分析
      用直方图,散点图分析累计消费
    • 4. 用户消费行为分析
      首购,用户分层,购买周期等分析

    2 项目开始

    2.1 数据预处理——清洗

    # 导入必备库
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from datetime import datetime
    %matplotlib inline    #‘%’内置的命令,jupyter专有的定义,比如在pycharm不常用到,inline意思是我做好图之后可以在html页面的单元格进行显示
    
    # 插入数据文件
    columns = ['user_id', 'order_dt', 'order_products', 'order_amount']
    df = pd.read_table('CDNOW_master.txt', names = columns, sep = "\s+")
    

    注意4点

    • 由于是txt文件,所以用方法 read.table 打开
    • txt 文件中字段未给出,所以需要传入4个列名以便于分析
    • 字段名称分别是 user_id:用户id, order_dt:购买日期,order_products:购买产品数,order_amount:购买金额,一般这四个字段是电商及消费相关的数据的重要指标
    • 一般csv文件时以逗号来分隔的,但是此份数据时通过空格来分割的,所以使用参数 '\s+' 处理任意个数的空格
    image.png
    image.png
    df['order_dt'] = pd.to_datetime(df.order_dt, format = '%Y%m%d') # Y表示四位数的日期部分,y表示两位数的日期部分
    df['month'] = df.order_dt.values.astype('datetime64[M]') # 增加一个 month 字段,转变时间维度便于分析
    
    image.png
    image.png
    image.png

    小结:至此,已完成数据的清洗

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

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

    2.2.1 每月消费总金额

    grouped_month = df.groupby('month')  # 按月进行聚合数据,形成新的对象
    order_month_amount = grouped_month.order_amount.sum()  # 求出订货量的总数
    order_month_amount.head()
    
    image.png image.png

    2.2.3 每月产品购买量

    • 前三个月消费订单量在10000上下,后续平均消费人数则在25000上下波动
    grouped_month.order_products.sum().plot()  # 每笔订单可能会有多个产品,可求出总产品的销售量
    
    image.png

    2.2.4 每月消费人数(需要去重)

    • 方法一
      image.png
      image.png
      image.png

    2.3 用户个体消费分析

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

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

    grouped_user = df.groupby('user_id')
    
    grouped_user.sum().describe()
    
    image.png

    2.3.2 用户消费金额和消费次数的散点图和直方图

    • 散点图可以揭示某种规律,直方图可以对用户进行分层
    grouped_user.sum().query('order_amount < 4000').plot.scatter(x = 'order_amount', y = 'order_products')
    
    image.png
    grouped_user.sum().query('order_products < 60').order_products.hist(bins = 40)  #
    
    image.png

    2.3.3 用户累计消费金额的占比

    理解:

    • 用户数量和总消费值的比例是随人数上升而不断累加的,所有用户与总消费额的比率是 1
    • 所以可以按升序排列出用户数量与总值的比
    • 最终可以用 apply 函数遍历cumsum 的累加和算出累加到当前用户数所占总用户的比例
    user_cumsum = grouped_user.sum().sort_values('order_amount').cumsum() / 2500315.63   # cumsum 为滚动累加求和
    user_cumsum
    
    image.png
    user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum() / x.sum())
    user_cumsum  # apply(lambda x:x.cumsum() / x.sum()),除数为占比,被除数为总数
    
    image.png
    user_cumsum.reset_index().order_amount.plot()  # user_cumsum 其实是一个series,reset_index 会把其转换为数据框,这样便于制图
                                                   # order_amount 也可用 order_products 代替,可得出几乎一样的结果
    
    image.png

    结论: - 前 2 万用户消费占比 0.4,后5千用户占比 0.6
    - 重点维系对象应放在这5千人上

    2.4 用户消费行为分析

    1. 用户第一次消费(首购)
      在很多行业里面首购是一个很重要的维度,它和渠道息息相关,尤其是针对客单价比
      较高客户留存率比价低的行业,第一次客户从哪里来可以拓展出很多运营方式。
      用户最后一次消费
    2. 新老客消费比
      • 多少用户仅消费了一次
      • 每月新客占比
    3. 用户分层
      • RFM
      • 新、老、活跃、流失
    4. 用户购买周期(按订单)
      • 用户消费周期描述
      • 用户消费周期分布
    5. 用户生命周期(按第一次&最后一次消费)
      • 用户生命周期描述
      • 用户生命周期分布
    image.png image.png image.png

    2.4.2 新老客户消费比

    从两个维度分析

    • 多少用户仅消费了一次
    • 每月新客占比
    user_life = grouped_user.order_dt.agg(['min', 'max'])  # 定义用户的购买周期
    user_life.head()
    
    image.png image.png

    2.4.3 用户分层

    • RFM:立方体模型。分别表示最近一次消费 (Recency)消费频率 (Frequency)消费金额 (Monetary)
    • 新、老、活跃、流失

    2.4.3.1 RFM

    rfm = df.pivot_table(index = 'user_id',
                         values = ['order_products', 'order_amount', 'order_dt'],  # 3 个字段,购买日期,购买金额,购买产品
                         aggfunc = {'order_dt':'max',
                                    'order_amount':'sum',
                                    'order_products':'sum'})  # 这里所求的是消费产品数,这样可以更加详细的区分
    rfm.head()
    
    image.png
    rfm['R'] = -(rfm.order_dt - rfm.order_dt.max()) / np.timedelta64(1, 'D')  # 客户最近一次购买日期减去今天(98年6月底)算出时间间距,
                                                                              # 由于时间类型是日期型,所以要转换为浮点数,除以天数去掉单位
    rfm.rename(columns = {'order_products':'F', 'order_amount':'M'},inplace =True)  # 统一下字段名
    rfm.head()
    
    image.png
    rfm[['R','F','M']].apply(lambda x : x - x.mean()).head()  # 每个客户在 R F M 三个维度上的值与平均值之差
    
    image.png
    def rfm_func(x):
        level = x.apply(lambda x:'1' if x >= 1 else '0')
        label = level.R + level.F + level.M  # 拼接为其中一种组合
        d = {                                # R F M 三个维度可以显示出一个客户的价值,三个维度可以细分为8种组合
            '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()
    
    image.png
    image.png
    rfm.loc[rfm.label == '重要价值客户', 'color'] = 'g'  # 后来赋予的颜色
    rfm.loc[~(rfm.label == '重要价值客户'), 'color'] = 'r' # 后来赋予的颜色
    rfm.plot.scatter('F', 'R', c = rfm.color)  # 不能直接赋予颜色,必须先赋值
    
    image.png
    image.png

    2.4.3.2 新、活跃、回流、流失和不活跃用户

    1. 可以先用数据透视表查看用户每月购买次数

    pivoted_counts = df.pivot_table(index = 'user_id',
                                    columns = 'month',
                                    values = 'order_dt',
                                    aggfunc = 'count').fillna(0)  # 没有消费的会用 0 进行填充
    pivoted_counts.head()
    
    image.png
    2. 简化模型(因为每月用户购买次数并不是重要数据,是否购买才是重点)
    image.png
    def active_status(data):
        status = []   
        for i in range(18):  # 遍历 18 个月的消费情况
            
            # 若本月没有消费
            if data[i] == 0:  # 判断是否为 0, 0 表示没有消费
                if len(status) > 0:  # 遍历18个月的情况后,如果其中一个月有消费,则长度大于 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()
    pivoted_purchase_status = pivoted_counts.apply(lambda x:pd.Series(active_status(x),index = indexs),axis=1)
    
    image.png
    purchase_status_ct = pivoted_purchase_status.replace('unreg',np.NaN).apply(lambda x : pd.value_counts(x))
    purchase_status_ct
    
    image.png image.png image.png image.png

    2.4.4 用户购买周期

    order_diff = grouped_user.apply(lambda x : x.order_dt - x.order_dt.shift())  # shift() 错位函数使数据依次向下移位,第一个值则会变为空值
    order_diff.head(10)
    
    image.png image.png image.png image.png

    结论:
    1. 订单周期呈指数分布
    2. 用户的平均购买周期是68天
    3. 绝大部分用户的购买周期都低于100天

    2.4.5 用户生命周期

    image.png
    image.png image.png

    2.5 复购率和回购率的分析

    • 复购率:自然月内,购买多次的用户占比
    • 回购率:曾经购买过的用户咋某一时期内的再次购买占比


      image.png
      image.png
      image.png
      image.png
    def purchase_back(data):  # 定义一个回购函数 
        status = []
        for i in range(17):  # 从第一个月开始遍历
            if data[i] == 1:  # 判断某一个月(从第一个月算起)是否有消费,如果有则分为下面两种情况
                if data[i + 1] == 1:  
                    status.append(1)  # 判断后一个月是否有消费,如果有则用 1 表示
                if data[i + 1] == 0:
                    status.append(0)  # 判断后一个月是否有消费,如果没有则用 0 表示
            else:
                status.append(np.NaN)  # 如果第一个月(前一个月)没有消费则用 NaN 表示
        status.append(np.NaN)
        return status
    
    indexs = df['month'].sort_values().astype('str').unique()
    purchase_b = df_purchase.apply(lambda x : pd.Series(purchase_back(x), index = indexs), axis = 1)
    purchase_b.head(5)
    
    image.png image.png

    相关文章

      网友评论

        本文标题:CD 网站上客户消费记录分析

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