美文网首页
python数据分析

python数据分析

作者: Kevin_pai | 来源:发表于2020-02-19 21:01 被阅读0次

    库版本

    库版本

    详情

    用户在CD网站上的消费记录。本次分析,通过这份数据分析用户的消费情况以及趋势,个体消费情况,以及回购率和复购率。

    导入数据

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    #显示图形(自动生成画布,只在jupyter notebook中有效)
    %matplotlib inline 
    columns=['user_id','order_dt','order_products','order_amount']
    df=pd.read_table(r'C:/Users/12585/Desktop/CDNOW_master.txt',names=columns,sep='\s+')
    
    • user_id:用户ID
    • order_dt:购买日期
    • order_prodects:购买产品数
    • order_amount:购买金额

    查询df内容

    df内容

    各种统计数据

    df.describe()
    
    统计数据

    其中,count代表总共有多少数据,mean代表平均值,std代表标准差,min代表最小值,max代表最大值。

    观察到,order_dt中日期处理成pandas中可以计算的日期格式,如下:

    df['order_dt']=pd.to_datetime(df.order_dt,format='%Y%m%d')
    #新增一个字段,将order_dt.values的日期转化成当月的第一天
    df['month']=df.order_dt.values.astype('datetime64[M]')
    

    再次查询此时df内容


    df内容

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

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

    每月的消费总金额

    # 按月归类
    grouped_month=df.groupby('month')
    #每个月消费金额
    order_month_amount=grouped_month.order_amount.sum()
    #显示部分数据
    order_month_amount.head()
    
    消费总金额
    #图形采用折线的方式
    plt.style.use('ggplot')
    #绘制order_month_amount数据的折线图,横轴代表月份,纵轴代表每个月的总金额
    order_month_amount.plot()
    
    月销售额趋势图

    说明:1997年年初的两个月作用销量陡增,接着断崖式下降,再趋于平稳。但是在接下来这一年的年初却未曾出现这种情况,推测这种销售情况可能由于某种特殊的原因导致的,且不容易复现。

    每月的消费次数

    grouped_month.user_id.count().plot()
    
    月消费次数

    说明:用户消费次数在前两个月较多,后暴跌,从四月份开始逐渐平稳。

    每月的产品购买量

    grouped_month.order_products.sum().plot()
    
    产品购买量

    说明:产品购买量的趋势同消费额和用户消费次数成正相关。

    每月的消费人数(去除重复消费的用户,得到每个月的用户数)

    # 这里 x 其实是一个数组,是每月分组的用户id,去重后求数组的 len 长度就代表每月的用户数
    df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates())).plot()
    
    每月消费人数

    和每月用户消费次数对比可知,顾客多次消费的人数不多,大多数都是一一个月来购买一次,具体什么原因导致有待后面的分析。

    用户个体消费分析

    即个体的消费情况分析。

    • 用户消费金额,消费次数的统计特征
    • 用户消费金额和消费次数的散点图
    • 用户消费金额的分布图
    • 用户消费次数的分布图
    • 用户累计消费金额占比(百分之多少的用户占了百分之多少的消费额)

    用户消费金额,消费次数的统计特征

    #按照用户分组
    grouped_user=df.groupby('user_id')
    #计算单个用户消费额
    grouped_user.sum().describe()
    
    用户消费统计

    说明:用户金额平均数在106左右,方差std较大,说明个体用户消费金额波动比较大。订单量的平均值为7单左右,方差std为17左右,波动相对而言较小。

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

    grouped_user.sum().plot.scatter(x='order_amount',y='order_products')
    
    消费额和购买量的关系图

    说明:从图中可知,消费次数和消费额成正相关。大部分客户消费在4000以下,购买数量在200以下。

    用户消费金额的分布图

    # 直方图,分为20块
    grouped_user.sum().order_amount.plot.hist(bins=100)
    
    顾客消费情况

    说明:从图中可知,大部分消费额都是比较集中,除去少部分异常值。大部分的消费额都在一千以内,客户购买力较小。下面除去较少的个别客户,得到更细致的更普遍的客户消费额分布趋势。

    # 直方图,分为20块,过滤
    grouped_user.sum().query('order_products<100').order_amount.plot.hist(bins=20)
    
    顾客消费情况

    用户消费次数的分布图

    grouped_user.sum().query('order_amount<2000').order_products.plot.hist(bins=20)
    
    顾客购买量直方图

    说明:从消费额和消费次数的离散图中可知,存在少数异常值干扰用户消费次数,所以设置一个过滤条件,从离散图中可知,消费额小于2000的状态较普遍。

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

    # cumsum 是求累加值
    user_cumsum=grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())
    # 这里 reset_index() 是为了得到一个自然数的行标签,表示的就是人数,下面的图就可以看出来多少个少占多少百分比
    user_cumsum.reset_index().order_amount.plot()
    
    消费额占比

    说明 :从图中可知,百分之五十的用户贡献了百分之十五的消费额,消费额前五千的消费总额占据了消费额的百分之六十。

    用户消费行为

    • 用户第一次消费(首购)
    • 用户最后一次消费
    • 新老客户消费比
      -- 多少用户仅消费一次
    • 用户分层
      -- RFM模型
      -- 新、老、活跃、回流、流失
    • 用户购买周期(按订单)
      -- 用户消费周期描述
      -- 用户消费周期分布
    • 用户生命周期(按第一次和最后一次消费) -用户生命周期描述
      -- 用户生命周期分布

    用户第一次消费(首购)

    # 得到最小的日期,然后统计一下各个日期的个数
    grouped_user.order_dt.min().value_counts().plot()
    
    user_id

    用户最后一次消费

    # 得到最大的日期,然后统计一下各个日期的个数,得到最后一次消费的情况,用户流失
    grouped_user.order_dt.max().value_counts().plot()
    
    最后一次消费日期统计

    新老客户消费比

    首先获得第一次和最后一次消费日期。
    #新老客消费比
    # 得到第一次和最后yc次消费情况,如果 min、max 日期相同,说明只消费了一次
    user_life=grouped_user.order_dt.agg(['min','max'])
    user_life.head()
    
    首购以及最后一次消费日期
    消费一次的客户数量。
    (user_life['min']=user_life['max']).value_counts()
    
    一次消费情况

    说明:一半用户只消费了一次。

    用户分层

    RFM模型
    # 画 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']= -(rfm.order_dt - rfm.order_dt.max())/np.timedelta64(1,'D')
    # 重命名,也就是 R:最后一次消费距今天数,F:消费总金额 ,M:消费总产品数
    # R :消费时间  F:消费金额  M:消费频次
    rfm.rename(columns={'order_products':"M",'order_amount':'F'},inplace=True)
    rfm.head()
    
    处理后数据

    )

    def rfm_func(x):
        level=x.apply(lambda x:'1' if x>=0 else '0')
        # level 的类型是 series,index 是 R、F、M
    #     print(type(level))
    #     print(level.index)
        label=level.R + level.F + level.M
        d={
            # R 为1 表示离均值较远即时间很久,F为1 表示 消费金额比较多,M 为1 表示消费频次比较多,所以是重要价值客户
            '111':'重要价值客户',
            '011':'重要保持客户',
            '101':'重要发展客户',
            '001':'重要挽留客户',
            '110':'一般价值客户',
            '010':'一般保持客户',
            '100':'一般发展客户',
            '000':'一般挽留客户',
        }
        result=d[label]
        return result
    
    # 注意这里是要一行行的传递进来,所以 axis=1,传递一行得到一个 111,然后匹配返回一个值
    rfm['label']=rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
    rfm.loc[rfm.label=='重要价值客户','color']='g'
    rfm.loc[~(rfm.label=='重要价值客户'),'color']='r'
    rfm.plot.scatter('F','R',c=rfm.color)
    
    消费金额和消费次数散点图
    rfm.groupby('label').sum()
    
    RFM模型
    用户生命周期 新客,活跃,回流,流失(一段时间不消费,或者不活跃)
    # 数据透视, userid为索引,月为列,求每月的消费次数,这里填充了
    pivoted_counts=df.pivot_table(index='user_id',
                                 columns='month',
                                 values='order_dt',
                                 aggfunc='count').fillna(0)
    pivoted_counts.head()
    
    用户月消费次数统计
    # 转变一下消费,有消费为1,没有消费为0
    df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
    df_purchase.tail()
    
    是否消费统计
    # 这里由于进行数据透视,填充了一些 null 值为0,而实际可能用户在当月根本就没有注册,
    #这样会误导第一次消费数据的统计,所以写一个函数来处理
    def active_status(data):
        status=[]
        # 数据一共有18个月份,每次输入一行数据,这样进行逐月判断
        for i in range(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
                        
    

    若本月没有消费,这里只是和上个月判断是否注册,有缺陷,可以判断是否存在就可以了

    • 若之前是未注册,则依旧为未注册
    • 若之前有消费,则为流失/不活跃
    • 其他情况,为未注册
      若本月有消费
    • 若是第一次消费,则为新用户
    • 如果之前有过消费,则上个月为不活跃,则为回流
    • 如果上个月为未注册,则为新用户
    • 初次之外,为活跃
      return:回流 new:新客 unreg:未注册 active:活跃
    df_purchase.apply(lambda x:pd.Series(active_status(x),index=df_purchase.columns),axis=1)
    purchase_stats.head()
    
    每月用户状态
    # 这里把未注册的替换为空值,这样 count 计算时不会计算到
    # 得到每个月的用户分布
    purchase_stats_ct=purchase_stats.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
    purchase_stats_ct
    
    统计每月各类用户数量
    # 又把null 值填充为0
    purchase_stats_ct.fillna(0).T
    # 绘制了一个面积图,蓝色是注册用户,一开始有后面没有用户进来
    purchase_stats_ct.fillna(0).T.plot.area()
    
    各类用户图形表示

    复购率和回购率分析

    复购率

    • 自然月内,购买多次的用户占比(即,购买了两次以上)

    回购率

    • 曾经购买过的用户在某一时期的再次购买的占比(可能是在三个月内)
    #查看每个用户每月购买次数
    pivoted_counts.head(10)
    
    消费情况
    # 区分一个,和一个以上的情况,以便于计算复购率,大于1为1,等于0为NaN,其它为0
    purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
    purchase_r.head()
    
    消费情况处理
    # 复购人数/总消费人数(不会计算nan值)
    (purchase_r.sum()/purchase_r.count()).plot(figsize=(10,4))
    
    复购率
    # 需要使用函数来判断是否回购:当月消费过的用户下个月也消费了叫做回购,这个定义可以改变
    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
    
    # 一行行的传递过去
    purchase_b=df_purchase.apply(lambda x:pd.Series(purchase_back(x),index=df_purchase.columns),axis=1)
    purchase_b.head()
    
    回购情况
    # 求得回购率,回购的次数处于总购买次数
    (purchase_b.sum()/purchase_b.count()).plot(figsize=(10,4))
    
    回购率

    相关文章

      网友评论

          本文标题:python数据分析

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