CD案例分析

作者: 分类讨论 | 来源:发表于2020-11-16 23:20 被阅读0次

    本文主要是主要是根据用户消费记录,分析用户消费行为,建立RFM模型,分析复购率、回购率等关键指标。希望对其他产品的线上消费数据分析有一定的借鉴价值。

    一、项目背景

    CDNOW是美国的一家网上唱片公司,成立于1994年,后来被贝塔斯曼音乐集团收购。

    二、分析目标

    本次分析报告的数据来源于这家CD网站上的用户消费记录,旨在分析用户消费行为,建立RFM模型,分析复购率、回购率等关键指标。

    三、主要分析框架

    image.png

    四、分析过程

    准备工作:

    # 导入数据包
    import pandas as pd
    import numpy as np
    # 导入数据
    columns = ['user_id','order_dt','order_products','order_amount']
    df = pd.read_table('bicycle_master.txt',names = columns,sep = '\s+',engine='python')
    df.head()
    # user_id:用户ID
    # order_dt:购买日期
    # order_products:购买产品数
    # order_amount:购买金额
    
    image.png
    # 查看数据类型及数据完整情况
    df.info()
    
    image.png

    通过查看数据类型发现,order_dt的数据类型是int64型,而非日期型,需要将其转化为日期型

    # 转化日期格式
    df['order_dt'] = pd.to_datetime(df.order_dt,format = "%Y%m%d")
    # 新增一列记录月,方便后续按月统计
    df['month'] = df['order_dt'].values.astype('datetime64[M]')
    df.head(1)
    
    image.png
    # 数据描述性统计
    df.describe()
    
    image.png

    从描述性统计可知:

    • 大部分订单只消费了少量商品(平均2.4),有一定值干扰
    • 用户的消费金额比较稳定,平均消费35元,中位数25元,有一定极值的干扰,导致平均消费被拉高,绝大多数订单的消费金额都小于35元

    1. 用户消费趋势分析

    根据月份分组,分别对消费额,购买人数,购买量,消费人数聚合

    # 根据月份分组
    grouped_month = df.groupby('month')
    # 聚合获得月消费次数
    order_month_amount = grouped_month.order_amount.sum()
    # 聚合获得月消费金额,月消费次数,月产品购买量
    grouped_month_info = grouped_month[['order_amount','user_id','order_products']].agg({'order_amount':'sum','user_id':'count','order_products':'sum'})
    # 重命名
    grouped_month_info.rename(columns = {'order_amount':'月消费金额','user_id':'月消费次数','order_products':'月产品购买量'},inplace = True)
    # 求消费次数
    grouped_month_info['消费次数'] = grouped_month['user_id'].unique().map(len)
    # 重置索引
    grouped_month_info = grouped_month_info.reset_index()
    grouped_month_info.head()
    
    image.png

    导出数据,PowerBI作图

    # 如果是日期类型,导入Power BI会是时间戳格式,所以这里转成字符串
    grouped_month_info['month'] = grouped_month_info['month'].astype('str')
    grouped_month_info.to_excel(r'group_month_infor.xlsx')
    
    image.png

    由上图可知

    • 消费金额在前三个月达到最高峰,后续消费较为稳定,有轻微下降趋势
    • 产品购买量在前三个月达到最高峰,后续消费较为稳定,有轻微下降趋势
    • 前三个月消费订单人数在10000笔左右,后续月份的平均消费人数则在2500人

    2. 用户个体消费分析

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

    对用户分组聚合

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

    根据用户购买数量看,max是1033,但是中位数只有3,而均值为7,所以可知有少部分的用户购买了大量的产品

    2.2 用户消费金额和消费次数的散点图
    对用户分组,对订单数及订单金额求和求得用户消费次数和消费金额
    grouped_user_info = grouped_user.sum()
    grouped_user_info.to_excel(r'.\临时表\用户个体消费行为分析.xlsx')
    
    image.png

    消费金额与产品消费数量成正相关

    2.3 用户消费金额的分布图
    # 获取用户消费金额
    grouped_user_sum_order_amount = grouped_user.sum()['order_amount']
    # 消费金额按照50分箱
    grouped_user_sum_order_amount_lst = [i for i in range(0,int(grouped_user_sum_order_amount.max())+50,50)]
    # 按照分箱规则对用户消费金额进行划分
    grouped_user_sum_order_amount = pd.cut(grouped_user_sum_order_amount,bins = grouped_user_sum_order_amount_lst,labels = grouped_user_sum_order_amount_lst[1:])
    # 导出数据
    grouped_user_sum_order_amount.to_excel(r'grouped_user_sum_order_amount.xlsx')
    
    image.png

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

    2.4 用户消费次数的分布图

    与消费金额分布情况相同,对消费次数进行分区

    #4. 用户消费次数的分布图
    grouped_user_sum_order_products = grouped_user.sum()['order_products']
    grouped_user_sum_order_products_lst = [i for i in range(0,int(grouped_user_sum_order_products.max())+50,50)]
    grouped_user_sum_order_products = pd.cut(grouped_user_sum_order_products,bins = grouped_user_sum_order_products_lst,labels = grouped_user_sum_order_products_lst[1:])
    grouped_user_sum_order_products.to_excel(r'grouped_user_sum_order_products.xlsx')
    
    image.png
    2.5 用户累计消费金额占比情况

    对用户分组,对消费金额排序后累加即可

    # 排序后使用cumsum对消费金额累加
    user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())
    user_cumsum.reset_index().order_amount.to_excel(r'user_cumsum_order_amount.xlsx')
    
    image.png

    3. 用户消费行为

    3.1 用户第一次消费(首购)
    # 按用户分组,取每个用户的最小日期,然后对最小日期计数并按照次数由大到小排序value_counts
    grouped_user_dt_min = grouped_user.min()['order_dt'].value_counts().reset_index().rename(columns = {'index':'first_date'})
    grouped_user_dt_min['first_date'] = grouped_user_dt_min['first_date'].astype('str')
    grouped_user_dt_min.to_excel(r'grouped_user_dt_min.xlsx')
    
    image.png
    3.2 用户最后一次消费

    与用户首购分布同理,获取用户最后一次购买日期的分布

    grouped_user_dt_max = grouped_user.max()['order_dt'].value_counts().reset_index().rename(columns = {'index':'last_date'})
    grouped_user_dt_max['last_date'] = grouped_user_dt_max['last_date'].astype('str')
    grouped_user_dt_max.to_excel(r'grouped_user_dt_max.xlsx')
    
    image.png

    大部分最后一次购买,集中在前三个月,大量用户购买了一次后就不再进行购买。

    3.3 新老客户消费占比
    3.3.1 多少用户只消费一次

    通过判断起始购买日期与最后购买日期,如果相等则任务是新客户,如果不等则为老客户

    user_life=grouped_user.order_dt.agg(['min','max'])
    # 统计只消费了一次的用户
    (user_life['min']==user_life['max']).value_counts()
    
    image.png

    可知,新客户占比51.1%

    3.3.2 每月新客占比

    分别对月与客户分组,获取每月每个客户第一次与最后一次购买日期,然后判断是否为新客,通过月份分组获得新老客户数量

    # 按月与用户分组,获得首购及最后一次购买日期
    group_um = df.groupby(['month','user_id'])['order_dt'].agg(['min','max'])
    # 新老客判断
    group_um['new'] = (group_um['min'] == group_um['max'])
    # 按月分组对新老客计数
    group_um.reset_index().groupby('month')['new'].value_counts()
    
    image.png
    3.4 用户分层RFM模型

    RFM模型介绍:
    RFM模型是衡量客户价值和客户创利能力的重要工具和手段。
    R:最近一次消费 (Recency)
    F:消费频率 (Frequency)
    M:消费金额 (Monetary)
    将以上三个指标分别拆分为二,这样就产生了8个维度用户客户的分组。R为1 表示比均值大,离最早时间近,F为1 表示消费金额比较多,M为1 表示消费频次比较多
    '111':'重要价值客户',
    '011':'重要保持客户',
    '101':'重要发展客户',
    '001':'重要挽留客户',
    '110':'一般价值客户',
    '010':'一般保持客户',
    '100':'一般发展客户',
    '000':'一般挽留客户',

    # 将消费记录表转透视表,user_id为行索引,分别对订单日期取最大值,订单金额汇总,订单产品数求和。
    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()
    
    image.png
    # 因为数据日期距今天比较久远,所以这里令表中日期的最大值为当前日期
    # 求R值
    RFM['R'] = (RFM.order_dt.max() - RFM.order_dt)/np.timedelta64(1,'D')
    # 重命名
    RFM = RFM.rename(columns = {'order_amount':'M','order_products':'F'})
    RFM.head()
    
    image.png

    将个用户分组,按照RFM的均值作为标准,比均值大就为1,比均值小就为0

    # 设定函数,如果
    def rfm_fumc(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
    # apply 默认axis = 0,按列映射
    RFM['label'] = RFM[['R','F','M']].apply(lambda x : x - x.mean()).apply(rfm_fumc,axis = 1)
    RFM.to_excel(r'RFM.xlsx')
    RFM.head()
    
    image.png
    image.png
    3.5 用户购买周期(按订单)
    3.5.1 用户消费周期描述

    购买周期,即用户每次购买的间隔

    # 利用shift将用户的购买日期向下偏移1行,然后相减就可以得到每次购买的间隔日期
    order_diff = grouped_user.apply(lambda x : x.order_dt - x.order_dt.shift())
    # 然后描述性统计
    order_diff.describe()
    
    image.png
    3.5.2 用户消费周期分布

    对用户的消费周期进行区间划分,然后对划分后的组进行分类计数即为消费周期的分布

    # 去掉相减后的单位days
    order_diff_info = (order_diff/np.timedelta64(1,'D'))
    # 指定分箱
    order_diff_cut_lst = [i for i in range(0,int(order_diff_info.max())+1,10)]
    # 按照分箱去分组划分
    order_diff_info_hist = pd.cut(order_diff_info,bins = order_diff_cut_lst,labels = order_diff_cut_lst[1:])
    # 用10填充NaN。NaN为第一次购买,所以没有周期
    order_diff_info_hist = order_diff_info_hist.fillna(10)
    order_diff_info_hist.to_excel(r'order_dt_diff_info.xlsx')
    
    image.png

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

    3.6 用户生命周期分布

    用户生命周期即为最后一次购买的日期减去第一次购买的日期。
    按照用户分组,获取第一次与最后一次够吗的日期,并求间隔

    # 分组获取第一次与最后一次购买日期
    user_life = grouped_user['order_dt'].agg(['min',max])
    # 获取购买周期
    user_life['user_life'] = user_life['max'] - user_life['min']
    user_life['user_life'] = user_life['user_life']/np.timedelta64(1,'D')
    

    对购买周期进行分组划分,统计各分组的频数可形成用户周期的分布图

    user_life_info = user_life['user_life']
    # 分箱,然后按照分箱分区划分,对于只购买一次的用户,不进行处理,即为NaN,后续在处理的时候不会统计NaN
    user_life_lst = [i for i in range(0,int(user_life_info.max()+10),10)]
    user_life_info_hist = pd.cut(user_life_info,bins = user_life_lst,labels = user_life_lst[1:])
    user_life_info_hist.to_excel(r'user_life_info_noNaN.xlsx')
    
    image.png

    4. 复购率和回购率分析

    复购率:自然月内,购买多次的用户占比
    本分析,定义复购为当月多次购买为复购
    回购率:曾经购买过的用户在某一时期的再次购买的占比
    本分析,定义上个月购买,这个月继续购买为回购。即周期为1个月

    4.1 复购率

    对df进行用户和月份的透视,值为用户单月购买的次数

    # 以用户为索引,月份为列,对订单进行计数,对于空值填充0,得到的值就为用户单月购买的次数
    pivoted_counts=df.pivot_table(index='user_id',
                                 columns='month',
                                 values='order_dt',
                                 aggfunc='count').fillna(0)
    pivoted_counts.head()
    
    image.png

    为了方便统计,我们把用户单月购买次数大于等于2的设为1,表示复购
    只有一次购买设置为0,表示有购买,没有复购
    没有购买的设置为NaN,表示未购买,方便后续算复购率

    purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
    purchase_r.head()
    
    image.png

    计算复购率

    # 每列的和即为当月的复购次数,每列的计数即为当月购买客户的数量
    purchase_r_reshop = (purchase_r.sum()/purchase_r.count()).reset_index(name = 'reshop')
    purchase_r_reshop['month'] = purchase_r_reshop['month'].astype(str)
    purchase_r_reshop.to_excel(r'purchase_reshop.xlsx')
    
    image.png
    4.2 回购率
    #在用户单月购买次数的表的基础上,将当月购买过标记为1,未购买过的标记为0
    df_purchase = pivoted_counts.applymap(lambda x : 1 if x > 0 else 0)
    df_purchase.head()
    
    image.png

    接下来判断是否回购,通过apply设置axis = 1,对每个用户逐个映射。
    先判断该用户本月是否购买,如果没购买:填充NaN,进行下一个月份的判断;如果购买:则判断下个月是否够购买,如果购买则即为复购1,否则为未复购0

    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)
        # 第18个月补充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()
    
    image.png

    计算各月的复购率

    # 对各列求和即为当月复购的次数,对各列计数即为当月购买的次数
    purchase_backshop = purchase_b.sum()/purchase_b.count()
    purchase_backshop.index = purchase_backshop.index.astype('str')
    purchase_backshop.to_excel(r'purchase_backshop.xlsx')
    
    image.png

    相关文章

      网友评论

        本文标题:CD案例分析

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