精华内容
下载资源
问答
  • 一、项目背景 CDNow是一家在线音乐零售平台,后...4.用户消费行为分析 5.复购率、回购率分析 0、导入数据、理解数据 0.1、导入常用的库 import pandas as pd import numpy as np %matplotlib inline import matplotlib.p
  • python数据分析实训--学生校园消费行为分析
  • 2020年中国礼物经济产业研究与用户消费行为分析报告 精简版.pdf
  • 2021年中国烘焙食品行业竞争格局与消费行为分析报告.rar
  • 2021年中国烘焙食品行业竞争格局与消费行为分析报告
  • 2018-2019中国礼物经济产业研究与用户消费行为分析报告.pdf
  • 基于大数据的网络用户消费行为分析.pdf
  • 淘宝用户消费行为分析.zip
  • 基于数据挖掘的校园一卡通消费行为分析.pdf
  • 基于数据挖掘技术的学生校园消费行为分析.pdf
  • 互联网时代大学生旅游产品消费行为分析——以东莞地区为例.pdf
  • 基于聚类算法的学生消费行为分析研究和应用.pdf
  • 文章目录数据分析之——用户消费行为分析内容摘要一、项目背景二、项目目的三、分析思路四、python数据分析实现五、PowerBI可视化看板设置 数据分析之——用户消费行为分析 内容摘要 项目背景 项目目的 分析思路 ...

    数据分析之——用户消费行为分析

    内容摘要

    • 项目背景
    • 项目目的
    • 分析思路
    • python数据分析实现
    • PowerBI可视化看板设置

    一、项目背景

    • 这是一份用户消费行为的分析报告;
      数据来源于网上,是用户在一家单车网站上的消费记录,其时间跨度为1997年1月至1998年4月。
    • 数据格式:txt文档,具体信息见图
      在这里插入图片描述
    • 第一列——user_id:用户ID
      第二列——order_dt:购买日期
      第三列——order_prodects:购买产品数
      第四列——order_amount:购买金额

    二、项目目的

    通过数据分析:
    1、了解本网站的基本营业情况;
    2、对用户行为进行分析,掌握用户的分布情况,便于之后的策略制定;

    三、分析思路

    1、基础数据整理清洗
    2、针对月份进行用户消费趋势的分析——便于掌握公司的营收发展趋势
    3、针对用户个体消费进行分析
    4、针对用户消费行为进行分析
    5、针对用户购买周期进行分析
    6、针对用户复购回购进行分析

    四、python数据分析实现

    • 一、基础数据整理清洗
      数据清洗的目的在于对数据进行审查和校验,其主要操作有:
      (1)解析原始数据列名,理解其意义并做通俗化替换;
      (2)查看数据源每一条信息的数据类型是否正确;
      (3)查看数据有无缺失值情况;
      (4)查看数据有无异常值情况;
      (5)数据一致化处理(多用于针对时间数据)

      • 首先导入数据,解析原始数据信息,做通俗化替换。
    #导入必要的包
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    #导入数据并设置列名
    #解析原始数据列名,理解其意义并做通俗化替换
    columns=['user_id','order_dt','order_products','order_amount']
    df=pd.read_table(r':\bicycle_master.txt',sep='\s+',names=columns)
    
    #查看数据
    df.head(2)
    

    在这里插入图片描述

    • 查看数据源每一列信息的数据类型是否正确,尤其需要注意可能会计算的数据和时间格式。
    #查数据源每一条信息的数据类型是否正确
    df.info()
    #发现其中order_dt 购买日期应该为时间格式类型,并非整型数据,需要进行数据处理
    

    在这里插入图片描述

    -数据源中时间数据的类型为整型,需要修改成datetime格式,并且为接下来时间序列分析做准备需要将年和月提取出来。

    #pd.to_datetime函数进行转换
    df['order_dt']=pd.to_datetime(df['order_dt'],format='%Y%m%d')
    #同时考虑到后续对数据分分析,将其按照年、月将时间提取出来
    #生成年、月
    df['Year']=df['order_dt'].astype('datetime64[Y]')
    df['Month']=df['order_dt'].astype('datetime64[M]')
    #查看数据
    df.head(2)
    

    在这里插入图片描述

    #查看数据描述
    df.describe()
    

    在这里插入图片描述

    • 发现大部分订单只消费了少量商品,75%用户的产品购买量仅3个;
      用户的消费金额比较稳定,平均消费35元,中位数在25元,存在一定极值的干扰。

    • 基础数据整理结束

    • 二、针对月份进行用户消费趋势的分析

      如果以天为尺度进行分析,具有较大的波动性和随机性,并且数据量较大;以月为尺度进行分析,能够避免一定的随机性,并且还可以看出一定的分布趋势,故选择以月为尺度进行数据分析。
      以月为尺度进行分析,较为重要的是消费金额,消费频率,购买产品量和消费人数
      消费人数的变化可以看出该平台对用户粘性的变化程度;消费水平一方面与消费人数有关,另一方面可能与当月的产品及活动有关。

      • 每月的消费总金额
      • 每月的消费次数
      • 每月的产品购买量
      • 每月的消费人数
    #需要对Month进行一个groupby,并对购买金额和购买产品数量进行求和,对购买次数(用户id)进行计数
    grouped=df.groupby(df['Month']).agg({"order_amount":'sum','user_id':'count','order_products':'sum'})
    grouped.head()
    

    在这里插入图片描述

    #统计每月的消费人数,即统计用户id唯一值的个数
    order_month_person=grouped_month.user_id.nunique()
    order_m_p=order_month_person.to_frame()
    order_m_p.head()
    

    在这里插入图片描述

    • 对用户人数统计可以看出,4月后出现明显的下跌趋势,将数据进行保存,用于后期powerbi绘图

    • 三、针对用户个体消费进行分析

      • 用户消费金额,消费个数描述性统计
      • 用户消费金额和消费次数的散点图
      • 用户消费金额的分布图
      • 用户消费次数的分布图
      • 用户累计消费金额占比
    #新建一个按照用户分类的数据
    user_info=df.groupby('user_id')
    #用户消费金额,消费个数描述性统计
    user_info.sum().describe()
    

    (1)用户消费金额,消费个数描述性统计
    在这里插入图片描述

    • 用户平均购买为7,但是中位值只有3,说明购买量大的用户占少数
    • 用户平均消费106元,中位值有43,判断同上,有极值干扰
      (2)用户消费金额和产品个数的散点图
    #用户消费金额和消费次数的散点图
    user_info.sum().plot.scatter(x='order_amount',y='order_products')
    

    在这里插入图片描述

    #绘制消费金额和消费个数的散点图
    user_cost_number=df.groupby('user_id').agg({'order_amount':'sum','order_products':'count'})
    user_cost_number.plot.scatter(x='number',y='cost')
    

    在这里插入图片描述
    (3)用户消费金额的分布图

    user_info.sum().order_amount.plot.hist(bins=20)
    #从直方图可知,用户消费金额,绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常
    

    在这里插入图片描述

    #使用切比雪夫定理过滤掉异常值,因为切比雪夫定理说明,95%的数据都分布在5个标准差之内,剩下5%的极值就不要了
    #order_amount (mean = 106 ,std = 241) mean+5std = 1311
    #过滤操作 pd.query(条件)
    user_info.sum().query('order_amount<1311').order_amount.plot.hist(bins=20)
    

    在这里插入图片描述

    (4)用户消费次数的分布图

    #过滤操作
    #先筛选再取数
    user_cost_number.query('number<50').number.plot.hist(bins=20)
    

    在这里插入图片描述

    (5)用户累计消费金额占比

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

    在这里插入图片描述

    • 四、针对用户消费行为进行分析
      • 用户第一次消费(首购)
      • 用户最后一次消费
      • 新老客户消费比
        • 多少用户仅消费一次
        • 每月新客占比
      • 用户分层
        • RFM模型
        • 新、老、活跃、回流、流失

    (1)用户第一次消费及最后一次消费

    grouped_user=df.groupby(df['user_id'])
    #第一次消费=消费时间最小=min()
    grouped_user.min().order_dt.value_counts().plot()	
    

    在这里插入图片描述

    #最后一次消费=消费时间最大=max()
    grouped_user.max().order_dt.value_counts().plot()
    

    在这里插入图片描述

    • 发现新用户仅在前三个月,随后便没有新用户的产生;最后一次消费呈现断崖式的下降

    (2)新老客户消费比

    • 多少用户仅消费一次
    • 每月一次消费与多次消费比例
    #仅消费一次说明第一次第一次消费时间=最后一次消费时间
    user_life=grouped_user.order_dt.agg([max,min])
    #选择第一次==最后一次的
    #统计数量
    (user_life['max']==user_life['min']).value_counts()
    
    """
    结果如下
    True     12054
    False    11516
    dtype: int64
    """
    
    • 有一半的用户,只消费了一次
    #每月新客占比
    #df.groupby(['Month','user_id']) 会有多个日期,因此pivot_table不显示order_dt
    grouped_um = df.groupby(['Month','user_id']).order_dt.agg(["min","max"])      #按月分组下的userid分组,求每月的最早购买日期和最晚消费日期
    grouped_um["new"] = (grouped_um["min"] == grouped_um["max"] )       # 新增列 True 为一次消费的用户
    
    #统计true和false的个数
    grouped_um.groupby(['Month']).new.value_counts()
    

    在这里插入图片描述
    (3)用户分层

    • 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()
    

    在这里插入图片描述

    # 得到最近一次消费,一般是计算 today 距离最近一次消费,这里因为时间太久远,就随便用的max值
    # 数值越大就越久远,分子得到的是一些天数类似 545 days(因为是时间格式相减),处以一个单位,就不会有单位了只留下数值
    #这里取负数是为了接下与mean比较是标定0、1而定的,因为越近越好,其时间越小
    rfm['R']= -(rfm.order_dt - rfm.order_dt.max())/np.timedelta64(1,'D')
    # 重命名,也就是 R:最后一次消费距今天数,F:消费总金额 ,M:消费总产品数
    # R :消费时间  F:消费金额  M:消费频次
    rfm.rename(columns={'order_products':"F",'order_amount':'M'},inplace=True)
    

    在这里插入图片描述

    #这里需要定义一个函数,针对RFM的表现进行8种类型的区分
    #这个RFM的标准都选择为其平均值
    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 分层可知,大部分用户是重要保持客户,但是这是由于极值的影响,所以 RFM 的划分标准应该以业务为准,也可以通过切比雪夫去除极值后求均值,并且 RFM 的各个划分标准可以都不一样
    • 尽量用小部分的用户覆盖大部分的额度,这样对之后计划的指定可以更具有针对性
    #新、老、活跃、回流、流失
    # 数据透视, userid为索引,月为列,求每月的消费次数,这里填充了
    pivoted_counts=df.pivot_table(index='user_id',
                                 columns='Month',
                                 values='order_dt',
                                 aggfunc='count').fillna(0)
    # 转变一下消费,有消费为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:活跃
    """
    
    #传入数据
    purchase_stats=df_purchase.apply(lambda x: pd.Series(active_status(x),index=df_purchase.columns),axis=1)
    

    在这里插入图片描述

    # 这里把未注册的替换为空值,这样 count 计算时不会计算到
    # 得到每个月的用户分布
    purchase_stats_ct=purchase_stats.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
    purchase_stats_ct
    

    在这里插入图片描述

    #计算各种占比
    returnratee=purchase_stats_ct.apply(lambda x:x/x.sum(),axis=0)
    #将NAN填充成0并转至
    purchase_stats_ct_info = purchase_stats_ct.fillna(0).T
    #绘制面积图
    purchase_stats_ct_info .plot.area()
    

    在这里插入图片描述

    • 五、针对用户购买周期进行分析
      • 用户购买周期(按订单)
        • 用户消费周期描述
        • 用户消费周期分布
      • 用户生命周期(按第一次和最后一次消费) -
        • 用户生命周期描述
        • 用户生命周期分布

    (1)用户购买周期(按订单)

    • 用户消费周期描述
    • 用户消费周期分布
    # 用户购买周期(按订单)
    #注意shift函数的使用
    # 计算相邻两个订单的时间间隔,shift 函数是对数据进行错位,所有数据会往下平移一下,所以可以
    order_diff=grouped_user.apply(lambda x:x.order_dt-x.order_dt.shift())
    order_diff.head(10)
    

    在这里插入图片描述

    #用户消费周期描述
    order_diff.describe()
    

    在这里插入图片描述

    #用户消费周期分布
    # 去除单元值np.timedelta64(1,'D'))
    (order_diff/np.timedelta64(1,'D')).hist(bins=20)
    

    在这里插入图片描述

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

    (2)用户生命周期(按第一次和最后一次消费)

    • 用户生命周期描述
    • 用户生命周期分布
    # 用户生命周期(按第一次和最后一次消费)描述
    (user_life['max']-user_life['min']).describe()
    

    在这里插入图片描述

    #用户生命周期分布
    ((user_life['max']-user_life['min'])/np.timedelta64(1,"D")).hist(bins=40)
    

    在这里插入图片描述

    • 用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
    • 用户均消费134天,中位数仅0天
    # 提取大于0的数据
    u_1=(user_life['max']-user_life['min']).reset_index()
    u_1
    

    在这里插入图片描述

    # 提取大于0的数据
    u_1=(user_life['max']-user_life['min']).reset_index()[0]/np.timedelta64(1,"D")
    u_1[u_1>0].hist(bins=40)
    

    在这里插入图片描述

    • 六、针对用户复购回购进行分析
      • 复购率
        • 自然月内,购买多次的用户占比(即,购买了两次以上)
      • 回购率
        • 曾经购买过的用户在某一时期的再次购买的占比(可能是在三个月内)
    # 复购率
    pivoted_counts.head(10)
    

    在这里插入图片描述

    # 区分一个,和一个以上的情况,以便于计算复购率,大于1为1,等于0 为0,等于1为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))
    

    在这里插入图片描述

    • 复购率稳定在20%所有,前一个月因为有大量新用户涌入,而这批用户只购买了一次,所以导致复购率降低
    #回购率使用的数据集
    df_purchase.head()
    

    在这里插入图片描述

    #回购率
    # 需要使用函数来判断是否回购:当月消费过的用户下个月也消费了叫做回购,这个定义可以改变
    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()
    

    在这里插入图片描述

    #计算比例
    purchase_b_backshop = purchase_b.sum()/purchase_b.count()
    #绘图
    purchase_b_backshop.plot()
    

    在这里插入图片描述

    五、PowerBI可视化看板设置

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 分析环境,对照附录一,理解字段含义。探查数据质量并进行缺失值和异常值等 方面的必要处理。将处理结果保存为“task1_1_X.csv”(如果包含多张数据表, X 可从 1 开始往后编号),并在报告中描述处理过程。 # _*_ ...

    任务 1 数据导入与预处理

    数据+生成数据 提取码:zxcv

    任务 1.1


    将附件中的 data1.csv、data2.csv、data3.csv 三份文件加载到
    分析环境,对照附录一,理解字段含义。探查数据质量并进行缺失值和异常值等
    方面的必要处理。将处理结果保存为“task1_1_X.csv”(如果包含多张数据表,
    X 可从 1 开始往后编号),并在报告中描述处理过程。

    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月09日
    import  pandas as pd
    df_1=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data1.csv',sep=',',encoding='gbk')
    df_2=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data2.csv',sep=',',encoding='gbk')
    df_3=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data3.csv',sep=',',encoding='gbk')
    combine=[df_1,df_2,df_3]
    for i in combine:
        print(i.isna().any())
    ##只有第二个表格里面有缺失值
    #查看确实情况
    print(df_2.isna().sum()/df_2.shape[0]*100)
    
    nul=[i[0] for i in df_2.isna().any().iteritems() if i[1]==True]
    
    

    对应的生成结果

    >>>for i in combine:
        	print(i.isna().any())
        
    Index           False
    CardNo          False
    Sex             False
    Major           False
    AccessCardNo    False
    dtype: bool
    Index        False
    CardNo       False
    PeoNo        False
    Date         False
    Money        False
    FundMoney    False
    Surplus      False
    CardCount    False
    Type         False
    TermNo       False
    TermSerNo     True
    conOperNo     True
    OperNo       False
    Dept         False
    dtype: bool
    Index           False
    AccessCardNo    False
    Date            False
    Address         False
    Access          False
    Describe        False
    dtype: bool
    
    ####可以看出只有表二有缺失值
    >>>print(df_2.isna().sum()/df_2.shape[0]*100)
    Index         0.000000
    CardNo        0.000000
    PeoNo         0.000000
    Date          0.000000
    Money         0.000000
    FundMoney     0.000000
    Surplus       0.000000
    CardCount     0.000000
    Type          0.000000
    TermNo        0.000000
    TermSerNo    98.601952
    conOperNo    99.951672
    OperNo        0.000000
    Dept          0.000000
    dtype: float64
    
    
    ##可以看出表二中缺失值比例过大,因此暂且不做处理。
    >>>nul=[i[0] for i in df_2.isna().any().iteritems() if i[1]==True]
    >>>nul
    ['TermSerNo', 'conOperNo']
    

    任务 1.2

    将 data1.csv 中的学生个人信息与 data2.csv 中的消费记录建立
    关联,处理结果保存为“task1_2_1.csv”;将 data1.csv 中的学生个人信息与
    data3.csv 中的门禁进出记录建立关联,处理结果保存为“task1_2_2.csv”。

    将表进行关联,用到concat函数:主要是用到了外部连接。

    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月09日
    import  pandas as pd
    df_1=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data1.csv',sep=',',encoding='gbk')
    df_2=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data2.csv',sep=',',encoding='gbk')
    df_3=pd.read_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data3.csv',sep=',',encoding='gbk')
    df1_2_1=pd.merge(df_1, df_2,how='right',on='CardNo')
    df1_2_2=pd.merge(df_1, df_3,how='right',on='AccessCardNo')
    
    """
    pd.cmerge(objs,how,om )
    常用参数说明:
    how:
    how{‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’}, default ‘inner’
    类似于SQL的左外,右外,外连接,内连接。
    left: use only keys from left frame, similar to a SQL left outer join; preserve key order.
    
    right: use only keys from right frame, similar to a SQL right outer join; preserve key order.
    
    outer: use union of keys from both frames, similar to a SQL full outer join; sort keys lexicographically.
    
    inner: use intersection of keys from both frames, similar to a SQL inner join; preserve the order of the left keys.
    
    on:连接时基准的参考列(也就是两张表都有的列)
    """
    df1_2_1.to_csv(r'C:\Users\yunmeng\Desktop\df1_2_1.csv',index=False,encoding='utf-8')
    
    df1_2_2.to_csv(r'C:\Users\yunmeng\Desktop\df1_2_2.csv',index=False,encoding='utf-8')
    

    任务 2 食堂就餐行为分析

    任务 2.1

    绘制各食堂就餐人次的占比饼图,分析学生早中晚餐的就餐地点
    是否有显著差别,并在报告中进行描述。(提示:时间间隔非常接近的多次刷卡
    记录可能为一次就餐行为)

    分析思路:
    首先采用的数据是,data2中的数据就可以,因为我们只需要得到食堂消费的数据。
    需要的处理是:对时间间隔非常接近的记录记为一次就餐行为。
    那么我们设定的判断是否重复就餐的标准是:
    出现在同一天,同一个人,时间间隔小于5分钟。
    然后就是进行数据的处理:
    整个流程如下。

    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月10日
    import pandas as  pd
    df=pd.read_csv(r"D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\data2.csv",encoding='gbk')
    #将‘Date’列转化为时间对象
    df['Date']=pd.to_datetime(df['Date'])
    da_li=df['Date'].to_list()
    #分别将每次消费的号数、小时、分钟等抽离出来。
    df['day']=[i.day   for i in da_li]
    df['hour']=[i.hour   for i in da_li]
    df['minute']=[i.minute   for i in da_li]
    df['day']=df['day'].astype(int)
    df['hour']=df['hour'].astype(int)
    df['minute']=df['minute'].astype(int)
    #将‘CardNo’列(卡号列)当做区分每一个学生的标准。
    st_no=df['CardNo'].value_counts().index.to_list()
    #用来存储需要删除的行的“Index”列的值,data2的数据中,有一列为‘Index’列,它是唯一的。
    index=[]
    #对每一个st_no进行遍历,相当于每次遍历取的是同一个学生的消费记录
    for i in st_no:
    	#用学生的“CardNo'的值来拿到一个学生的所有消费记录
        da=df[df['CardNo'] == i]
        #获得这个学生的消费的天数的列表
        day_li=da['day'].value_counts().index.to_list()
        for j in day_li:
        	#拿到这个学生的同一天的消费记录
            db=da[da['day']==j]
            #对同一天的消费记录,进行遍历。每一个消费记录和他之后的消费记录进行判断。
            for l in range(len(db)-1):#每一个(除了最后一个)的消费记录
                for k in range(l+1,len(db)-1):#在上面的,第i个消费记录后的消费记录
                #进行判断,如果小时数相等&分钟数相小于5那么就将“Index”的值记录下来,然后,判断完这个记录后就直接跳出循环,进行第二条记录的判断了。
                    if ((db.iloc[l:l+1,:]['hour'].to_list()[0]==db.iloc[k:k+1,:]['hour'].to_list()[0])&(abs(db.iloc[l:l+1,:]['minute'].to_list()[0]-db.iloc[k:k+1,:]['minute'].to_list()[0])<=5)):
                        index.append(db.iloc[l:l+1,:]['Index'].to_list()[0])
                        continue
    #得到原来数据的复制本进行操作,不改变源数据。
    de=df.copy()
    #将“Index”列设置为索引列。
    de=de.set_index('Index')
    #去除重复了的“Index”的值
    result=de.drop(index,axis=0)
    #将结果保存到本地。
    result.to_csv(r'C:\Users\yunmeng\Desktop\df2_1.csv',encoding='utf-8')
    
    >>>result.shape#处理后行数
    (388592, 16)
    >>>df.shape#处理前行数
    (519367, 17)
    

    对上述数据用tableau进行可视化分析如图所示。
    3餐的消费数据

    对统计的3餐的消费数据可以得出如下结论:
    ![请添加图片描述](https://img-blog.csdnimg.cn/95c358258a094772a2c66f609f2b4f6b.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5LqR5qKm5LmL5LiK,size_20,color_FFFFFF,t_70,g_se,x_16)
    
    可以看到,学生在早中晚餐的就餐地点是有差别的。
    早餐时间:大部分同学的选择依次是:第二食堂、第五食堂、第一食堂、好利来食品店。
    中餐时间:大部分同学的选择依次是:第二食堂、第五食堂、第四食堂、第三食堂、第一食堂、好利来食品店。
    晚餐时间:大部分同学的选择依次是:第二食堂、第五食堂、第四食堂、第三食堂、第一食堂、好利来食品店。
    可见:第二、五食堂的早餐更受欢迎
    中餐各食堂消费整体平均。
    二五食堂营业领先。
    同时,在0-6点期间,大部分统计去的是二食堂,说明二食堂营业时间最长,大晚上也有买吃的。
    
    总体来讲,
    3,4食堂:都是在中餐和晚餐时间为主营时间段
    1,5食堂:3餐都为主要营业时间段
    2食堂:3餐都为主要营业时间段,但在早餐时间业务最为繁忙,需要增加人员
    

    不同时间的的营业高峰

    不同时间的的营业高峰,可以看出:
    高分期分别为:
    早餐:7.00-8.00
    中餐:11:00-13.00
    晚餐:17:00-19:00
    所以食堂要在这几个点增加人员的部署。
    

    任务 2.2


    通过食堂刷卡记录,分别绘制工作日和非工作日食堂就餐时间曲
    线图,分析食堂早中晚餐的就餐峰值,并在报告中进行描述。

    由于作图的需要,需要区分工作日与节假日,所以得加一列数据作为是否为假期。
    参考方法:python pandas 怎么判断一天是否为工作日+计算距离特定时间之间的天数

    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月10日
    import pandas as pd
    from chinese_calendar import is_workday
    df=pd.read_csv(r'C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\df2_1.csv',encoding='utf-8')
    df['Date']=pd.to_datetime(df['Date'])
    df['Date'].map(lambda x:is_workday(x))
    df['is_workday']=df['Date'].map(lambda x:is_workday(x))
    df.to_csv(r'C:\Users\yunmeng\Desktop\df2_2.csv',encoding='utf-8')
    

    工作日与非工作日一天24小时的消费记录图
    请添加图片描述

    请添加图片描述

    请添加图片描述

    不同时间的的营业高峰,可以看出:
    工作日:高分期分别为:
    早餐:6.00-8.00
    中餐:10:00-12.00
    晚餐:17:00-19:00
    非工作日:高分期分别为:
    早餐:7.00-10.00
    中餐:10:00-12.00
    晚餐:17:00-19:00
    所以食堂要在这几个点增加人员的部署。
    

    任务 2.3


    根据上述分析的结果,为食堂的运营提供建议。

    任务 3 学生消费行为分析

    任务 3.1


    根据学生的整体校园消费数据,计算本月人均刷卡频次和人均消
    费额,并选择 3 个专业,分析不同专业间不同性别学生群体的消费特点。

    得出的本月人均刷卡频次和人均消费额
    >>>money_average
    245.81
    >>>fre_average
    60.14
    
    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月11日
    import  pandas as pd
    df=pd.read_csv(r'C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\df1_2_1.csv',encoding='utf-8')
    #读取学生的数据表
    df2=pd.read_csv(r'C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\data1.csv',encoding='gbk')
    #计算所有的学生数
    stu_num=df['CardNo'].value_counts().count()
    #计算消费的总金额
    consum_total=df['Money'].sum()
    #得出对于所有人的:月平均消费频率,月平均消费金额
    money_average=round(consum_total/stu_num,2)
    fre_average=round(df['CardNo'].count()/stu_num,2)
    
    
    #获得每个学生的月消费频率
    count=df['CardNo'].value_counts().to_list()
    CardNo=df['CardNo'].value_counts().index.to_list()
    df_count=pd.DataFrame({"count":count,'CardNo':CardNo})
    
    #获得每个学生的消费均值
    Mean=df.groupby('CardNo').mean()['Money'].to_list()
    cardno=df.groupby('CardNo').mean()['Money'].index.to_list()
    df_mean=pd.DataFrame({'mean':Mean,'CardNo':cardno})
    
    #得到每个学生消费均值,消费频率与学生信息的合并表格
    data1=pd.merge(df_mean,df_count,how='outer',on='CardNo')
    data2=pd.merge(df2,data1,how='right',on='CardNo')
    data2.to_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\df3_1.csv',index=False,encoding='gbk')
    
    

    选取:18电子商务、18工程造价、18工商企管3个专业进行可视化分析

    从专业上看:18电子商务、18工程造价、18工商企管。
    18电子商务和18工商企管专业的学生的,学生消费均值,消费频率均比18工程造价专业的更高
    

    专业上看

    从专业和性别上看
    

    选择3个专业的学生进行分析

    任务 3.2


    根据学生的整体校园消费行为,选择合适的特征,构建聚类模型,
    分析每一类学生群体的消费特点。

    思路:
    用到的数据要全面,因此对提供的数据进行feature的提取。(加上3.1中提取的2个数据,总共提取了5个数据)
    所以,需要用到,任务3.1的人均刷卡频次和人均消费额的数据:df3_1
    data3中门禁的信息数据:得到一个feature:每个人最常去的地点(address_most)
    data2中的消费数据:得到2个feature:总消费次数(CardCount)、消费最常去的地点(consum_most_add)
    最终得到的feature:

    featuremeaning
    ‘Sex’性别
    ’Major‘专业
    ‘mean’单次消费平均额
    ‘count’一个月的消费数
    ‘address_most’门禁表格中统计的最常去的地方
    ‘CardCount’卡的总共消费次数
    ‘consum_most_add’消费最长去的地方

    将此7个特征作为分类标准进行分类,分为5类

    # _*_ coding:utf-8 _*_
    # 作者:yunmeng
    # 日期:2021年11月12日
    import copy
    import  numpy as np
    import pandas as pd
    from sklearn.cluster import  KMeans
    #每个学生的消费频率和平均消费情况
    #作为核心的表格,在此基础上进行数据的添加
    df=pd.read_csv(r"C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\df3_1.csv",sep=",",encoding="gbk")
    #student info
    data1=pd.read_csv(r"C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\data1.csv",sep=",",encoding="gbk")
    #消费信息的表格
    data2=pd.read_csv(r"C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\data2.csv",sep=",",encoding="gbk")
    #门禁信息的表格
    data3=pd.read_csv(r"C:\Users\yunmeng\Desktop\泰迪标准代码文件\学生消费\data3.csv",sep=",",encoding="gbk")
    df3=data3.copy()
    df3['Address']=df3['Address'].str.extract('(.*?)\[')
    add_nama=df3.Address.value_counts().index.to_list()
    data3_stu=df3['AccessCardNo'].value_counts().index.to_list()
    result=[]
    for i in data3_stu:
        tem_da=df3[df3['AccessCardNo']==i]
        #tem_da['Address'].value_counts().index.to_list()[0]
        tem_dic=tem_da['Address'].value_counts().to_dict()
        result.append(max(tem_dic,key=tem_dic.get))
    
    ###feature
    address_most=pd.DataFrame({'AccessCardNo':data3_stu,'address_most':result})
    ########################################################
    #对表二操作
    df2=data2.copy()
    ####feature
    card_count_gross=pd.DataFrame(df2.groupby('CardNo')['CardCount'].max().reset_index())
    data2_stu=df2['CardNo'].value_counts().index.to_list()
    result_2=[]
    for i in data2_stu:
        tem_da = df2[df2['CardNo'] == i]
        # tem_da['Address'].value_counts().index.to_list()[0]
        tem_dic = tem_da['Dept'].value_counts().to_dict()
        result_2.append(max(tem_dic, key=tem_dic.get))
    #####feature
    consum_most_add=pd.DataFrame({'CardNo':data2_stu,'consum_most_add':result_2})
    ###合并所有的feature
    #feature:   address_most
    #feature:   card_count_gross
    #feature:   consum_most_add
    df_1=pd.merge(df,address_most,on='AccessCardNo',how='left')
    df_2=pd.merge(df_1,card_count_gross,on='CardNo',how='left')
    df_3=pd.merge(df_2,consum_most_add,on='CardNo',how='left')
    
    ######################################
    #对合并后的数据进行标注话处理,转化为数值型数据
    deal=copy.deepcopy(df_3)
    #删除没有用的列
    deal.drop('Index',axis=1,inplace=True)
    deal.drop('AccessCardNo',axis=1,inplace=True)
    #查看一下每一列数的数据的类型情况
    for col in deal.columns:
        print(f"{col}: \n{deal[col].unique()}\n")
    #得到非数据类型(对象类型)的数据的列名。
    obj=[i for i in deal.columns if deal[i].dtype=='O']
    #定义函数:对其中的不同类型的值转化为对应的数字。
    def rep(repname):
        major = deal[repname].unique().tolist()
        major_dic = dict(zip(major, np.arange(len(major))))
        deal[repname] = deal[repname].map(major_dic)
        print(major_dic)
    for i in obj:
        rep(i)
    #定义函数:查看每列数据间的方差,并把方差大于5的列名输出,同时排除CardNo列(为学号,后期分类不考虑)。
    adj_name=[i for i in deal.columns if (deal[i].var()>5)&(i!='CardNo')]
    #定义函数:对每一列的数进行取log(x+1),标准化
    def adj(adjname):
        deal[adjname]=np.log(deal[adjname]+1)
    for i in adj_name:
        adj(i)
    #######################
    #进行分类模型的搭建
    model=KMeans(n_clusters=5, random_state=0).fit(deal)
    deal['type']=model.labels_
    pd.DataFrame(model.labels_).value_counts()
    #聚类的中心
    model.cluster_centers_
    #得出分类的结果后,添加进原数据列,进行数据的保存导出为df3_2
    final_result=pd.merge(df_3,deal[['CardNo','type']],how='left',on='CardNo')
    
    final_result.to_csv(r'D:\Users\yunmeng\PycharmProjects\数据分析\泰迪\相关文件\df3_2.csv',index=False,encoding='gbk')
    

    用tableau进行可视化分析:
    请添加图片描述

    从图中看,这5类消费人群的特征
    分为5类:
    高:1  消费次数少,单价高,总消费次数少、高
    中上:0  消费次数高,消费单价高,总次数中
    中:1   消费次数多,消费单价低,总次数少
    较低:3   消费次数低,消费单价低,总次数较低
    低:4   消费次数少,消费单价低,总次数多
    

    请添加图片描述
    请添加图片描述

    任务 3.3(还未做)


    通过对低消费学生群体的行为进行分析,探讨是否存在某些特征,
    能为学校助学金评定提供参考。

    展开全文
  • 用户消费行为分析

    千次阅读 2020-08-21 15:49:52
    3.1 用户总体消费行为分析 3.1.1 每月产生的总订单数 从结果可用看出: 统计每个月的CD销量。前3个月的销量数据相对较高,有异常。而后期的销量则很平稳。 假设出现的原因: 用户数据异常值。 有促销活动。 某一

    1. 项目简介

    数据来源:CDNow网站的用户在1997年1月1日至1998年6月30日期间内购买CD交易明细。
    数据集字段:用户ID,购买日期,订单数,订单金额。
    目标:通过各个指标对用户行为进行分析,更清楚了解用户行为习惯,为进一步制定营销策略提供依据。

    2. 思路

    在这里插入图片描述

    3. 具体分析

    3.1 用户总体消费行为分析

    3.1.1 每月产生的总订单数

    在这里插入图片描述
    从结果可用看出:
    统计每个月的CD销量。前3个月的销量数据相对较高,有异常。而后期的销量则很平稳。
    假设出现的原因:

    1. 用户数据异常值。
    2. 有促销活动。
    3. 某一(或多名)知名歌手发布新曲专辑。

    3.1.2 每月产生的总消费金额

    在这里插入图片描述
    从结果可用看出:
    每月产生的总消费金额变化趋势与每月产生的总订单数的变化趋势相似,两者产生的原因相似。

    3.1.3 每月消费的总人数

    在这里插入图片描述

    3.1.4 每月平均每人的订单数

    在这里插入图片描述

    3.1.5 每月平均每人产生的消费金额

    在这里插入图片描述

    3.2 用户个体消费行为分析

    3.2.1 第一次消费的用户人数与时间的关系

    在这里插入图片描述
    由图可以看出,大概在97年3月末之后就没有新增用户了.

    3.2.2 最后一次消费的用户人数与时间的关系

    在这里插入图片描述
    从结果可以看出:

    1. 用户第一次购买分布,集中在1997的前三个月,其中,在 2 月 11 日至 2 月 25 日有一次剧烈波动。
    2. 用户最后一次购买的分布比第一次分布广,但是大部分最后一次购买也集中在前三个月,说明忠诚用户较少,随着时间的递增,最后一次购买数在递增,消费呈现流失上升的趋势,

    3.2.3 只消费一次的用户占比

    在这里插入图片描述
    在这里插入图片描述
    从结果可以看出:
    在刚刚开始的3个月内存在着每月只消费一次的用户,但占比逐月减少,到3个月后就没有每个月只消费一次的用户,说明销售市场已经被打开,口碑逐渐提高。

    3.2.4 用户分层

    3.2.4.1 RFM分层

    R:最近一次消费时间
    F:消费频率
    M:消费金额
    在这里插入图片描述
    从图中可以看到:
    从 RFM 分层可知,大部分用户为重要保持客户和一般发展客户,且购买频次基本在在200以内。

    3.2.4.1 用户活跃度分层

    将用户划分为:未注册、新用户、活跃用户、不活跃用户、回流用户、持续活跃用户、流失用户。
    在这里插入图片描述
    在这里插入图片描述

    3.2.5 用户购买周期

    在这里插入图片描述
    从结果可以看到:

    1. 订单的周期大致呈指数分布,绝大部分用户的购买周期集中在前100天。
    2. 用户的平均购买周期是 68 天。
    3. 可以看到在购买后10天之内的用户重复购买的用户比较多,此时在消费10天发放优惠卷或代金券用于促进消费,消费后60天短信推送最新的信息比如优惠或是新发的专辑信息用于唤醒于用户。

    3.2.6 用户生命周期

    在这里插入图片描述
    客户的平均生命周期是135天,最长生命周期是544天。中位数 0 天,大部分用户第一次消费也是最后一次,这批属于低质量用户,而最大的是 544 天,几乎是数据集的总天数,这用户属于核心用户。
    在这里插入图片描述
    从结果可用看出:

    1. 生命周期在 50 天内的用户属于低质量用户,应采取尽量引导购买的措施,提高用户转化率。
    2. 少部分用户集中在 50-300 天,属于普通用户,忠诚度一般。
    3. 集中在 300-400 天以后的,属于忠诚用户。
    4. 部分大于 400 天的用户已经属于核心用户,忠诚度极高,应尽量维护这批用户的利益。

    3.3 复购率和回购率分析

    3.3.1 复购率

    月复购率: 在一个月内消费两次及以上的用户在总消费用户中占比
    在这里插入图片描述
    从结果可用看出:

    1. 前三个月大量新客增加,复购率不高,在5%-15%之间,但在猪圈增加,在3月后的用户数开始稳定,使得复购较稳定,在20%左右。
    2. 复购率的平均值为0.194745,说明在一个月内每5个消费者中中就有1个人消费两次及以上。

    3.3.2 回购率

    在这里插入图片描述
    从结果可用看出:

    1. 回购率与复购率的变化趋势一致。前三个月的回购率较低,3月后回购率稳定在30%左右。
    2. 用户回购率高于复购率,
    3. 根据复购率和回购率可知,老客的复购和回购远高于新客,忠诚度更高,这是 CDNow 网站的用户消费特征。

    代码链接:https://github.com/guotianyi960531/CDNow-.
    参考:
    [1]python数据分析实战.
    [2]数据分析实战项目| 用户消费行为的分析报告.
    [3]CDNow网站的用户购买明细分析.
    [4]CDNow网站用户消费行为分析.

    展开全文
  • Python用户消费行为分析实例

    千次阅读 2018-10-10 23:44:14
    由于手头用户消费数据的缺失我们这次采用专栏的数据进行实战。原数据在此:链接: https://pan.baidu.com/s/1IMd1ZOm2sTQSu-JKBAfy2A 提取码: dg38 #首先还是常规的导入库和读取文件 import ...

    本文借鉴于知乎用户秦路的专栏https://zhuanlan.zhihu.com/p/27910430,这里只是自己理解基础上加以扩充和整理修改,丰富细节。

    由于手头用户消费数据的缺失我们这次采用专栏的数据进行实战。原数据在此:链接: https://pan.baidu.com/s/1IMd1ZOm2sTQSu-JKBAfy2A 提取码: dg38

    #首先还是常规的导入库和读取文件
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    from datetime import datetime
    #设定绘图风格
    plt.style.use('ggplot') 
    #由于原数据没有列名,我们手动传入列名列表,并以任意空格为分隔符号
    columns = ['user_id', 'order_dt', 'order_products', 
    'order_amount']
    df =pd.read_table(r'/Users/herenyi/Downloads/
    CDNOW_master.txt', names = columns, sep = '\s+')
    #查看下读取后的数据集概况
    df.head()
    df.describe()
    df.info()
    

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    从上可知,这是一个关于用户购买某项东西的消费记录,主要有用户ID,购买时
    间,订单个数和订单金额四项,平均每笔订单消费金额为35美金,标准差为36美
    金,中位数为25,也就是说平均数大于中位数,也就是正偏分布,大多数用户消费
    金额集中在小额,小部分用户贡献大额消费,符合消费类数据的二八分布。由于没
    有空缺数据,可以不用清理直接开始分析,同时我们注意到日期数据是整数型,需
    要转换成时间格式。

    #加入两个时间新列
    df['order_date'] = pd.to_datetime(df.order_dt, format ='%Y%m%d')
    df['month'] = df.order_date.values.astype('datetime64[M]')
    df.head()
    

    在这里插入图片描述
    pd.to_datetime可以将特定的字符串或者数字转换成时间格式,其中的format参数表
    示输出的格式,%Y匹配四位数年份,%m匹配月份,%d匹配日期。若想输出year-
    month-day这形式,则是%Y-%m-%d。

    astype也可以将时间格式进行转换,比如[M]转化成月份。我们将月份作为消费行为
    的主要事件窗口,选择哪种时间窗口取决于消费频率。

    #按用户ID进行分组
    user_grouped = df.groupby('user_id').sum()
    user_grouped.head()
    user_grouped.describe()
    

    在这里插入图片描述
    由于原表只按订单来记录,按用户分组下看下数据集概述,毕竟我们这是用户消费
    行为分析。从用户角度看,每位用户平均购买7张CD,最多的用户购买了1033张,
    属于狂热用户了。用户的平均消费金额100元,标准差是240,中位数是3张,说明
    是长尾分布,存在小部分购买多张碟的高消费用户。下面我们就开始按月度来进行
    分析。

    #导入中文
    from matplotlib.font_manager import FontProperties
    chinese = FontProperties(fname = r'/Users/Shared/Epic Games/Fortnite/Engine/Content/Slate/Fonts/DroidSansFallback.ttf')
    ax = df.groupby('month').order_amount.sum().plot()
    ax.set_xlabel('月份', fontproperties=chinese) 
    ax.set_ylabel('消费金额(美元)', fontproperties=chinese) 
    ax.set_title('不同月份的用户消费金额', fontproperties=chinese) 
    
    ax = df.groupby('month').order_amount.sum().plot()
    ax.set_xlabel('月份', fontproperties=chinese) 
    ax.set_ylabel('CD碟数(张)', fontproperties=chinese) 
    ax.set_title('不同月份的用户购买张数', fontproperties=chinese) 
    

    在这里插入图片描述
    在这里插入图片描述
    由图片可知,无论是消费金额还是CD碟数都呈现相同的趋势,而且前三月数据都呈
    现出异常状态,由于我们不知道原数据到底从何获得,只能做出这三个月有促销活
    动,抑或是这是新开的店之类的,前三个月大多都是新人之类的假设,我们不得而
    知,继续往下看。

    ax = df.groupby('user_id').sum().plot.scatter('order_amount', 'order_products')
    ax.set_xlabel('消费金额', fontproperties=chinese) 
    ax.set_ylabel('CD碟数(张)', fontproperties=chinese) 
    ax.set_title('每个用户消费金额与购买个数的关系', fontproperties=chinese)
    

    在这里插入图片描述
    这是用户的消费金额与购买数量的关系。可以看到,因为是cd网站的消费记录,产
    品价格没有太大区间差别,每个用户的消费金额跟购买数量呈现一定的线性关系。
    为了更好的观察,我们尝试用直方图来呈现数据.

    plt.figure(figsize = (12,4))
    plt.subplot(121)
    ax = df.groupby('user_id').order_products.sum().hist(bins = 50)
    ax.set_xlabel('CD碟数(张))', fontproperties=chinese) 
    ax.set_ylabel('用户数(人)', fontproperties=chinese) 
    ax.set_xlim(0,150)
    ax.set_title('用户购买碟数分布直方图', fontproperties=chinese)
    plt.subplot(122)
    ax = df.groupby('user_id').order_amount.sum().hist(bins = 50)
    ax.set_xlabel('消费金额(美元)', fontproperties=chinese) 
    ax.set_ylabel('用户数(人)', fontproperties=chinese) 
    ax.set_xlim(0,2000)
    ax.set_title('用户消费金额分布直方图', fontproperties=chinese)
    

    在这里插入图片描述

    我们可以从直方图看到,大部分用户的消费能力确实不高,整个计算周期里的购买
    碟数在20张以内,消费金额在200美金以内,再图上几乎看不到高消费用户,这也
    确实是典型的消费行业规律。观察完用户消费的金额和购买量,接下来看看消费行
    为的时间节点。

    df.groupby('user_id').month.min().value_counts()
    df.groupby('user_id').month.max().value_counts()
    

    在这里插入图片描述
    在这里插入图片描述

    我们可以看到,貌似每个用户的第一次购买记录都是前三个月,最后次购买记录也
    是前三个月居前三。由此我们可以推测,这份数据集大概是选择了这三个月时间段
    消费的用户在后面的18个月的追踪记录数据。也能很好的解释我们之前看到的前三
    个月无论是消费金额还是购买数量的异常。

    这之中,很多用户的第一次消费就是最后次消费,说明这些用户已然流失,更多细
    节我们需要对数据进一步划分。为了避免混淆,这里统一将这数据集的用户定义为
    前三个与的新客。

    消费行为中的复购率和回购率

    复购率:复购率的定义是在某时间窗口内消费两次及以上的用户在总消费用户中占
    比。这里的时间窗口是月,如果一个用户在同一天下了两笔订单,这里也将他算作
    复购用户。

    #创建数据透视表,对每个用户的每月订单数计数
    pivoted_counts = df.pivot_table(index = 'user_id', columns = 'month', values = 'order_dt', aggfunc = 'count' ).fillna(0)
    pivoted_counts.head()
    #进行数据转化,把消费两次及以上记为1,消费一次记为0,没有消费记为NaN
    pivoted_counts_transf = pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x == 0 else 0)
    #计算复购率并作图
    ax = (pivoted_counts_transf.sum()/pivoted_counts_transf.count()).plot(figsize = (10,4))
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('百分比(%)', fontproperties=chinese) 
    ax.set_title('每月用户复购率图', fontproperties=chinese)
    
    

    在pandas中,数据透视有专门的函数pivot_table,功能非常强大。pivot_table参数
    中,index是设置数据透视后的索引,column是设置数据透视后的列,简而言之,
    index是你想要的行,column是想要的列。案例中,我希望统计每个用户在每月的订
    单量,所以user_id是index,month是column。

    values是将哪个值进行计算,aggfunc是用哪种方法。于是这里用values=order_dt和
    aggfunc=count,统计里order_dt出现的次数,即多少笔订单。使用数据透视表,需
    要明确获得什么结果。有些用户在某月没有进行过消费,会用NaN表示,这里用fillna填充。

    lambda为自建函数,之前已经讲过,用到条件语句时,要注意没有elif,两个判断时
    需要两个if语句,并且呈现 结果1 if else(结果2 if XX else 结果3)这样的倒装结
    构,applymap则是作用到数据里的每一个数据时使用,接下来我们看图。
    在这里插入图片描述
    在这里插入图片描述
    从图中我们可以看出复购率因为大量新用户加入的关系,不断扩大分母,导致初期
    的复购率不怎么高,譬如刚开始的97年一月份复购率只有6%左右,而后直线上升,
    到第四个月后到达最高点,因为这次数据集是前三个月新客跟踪数据,三个月后,
    没有新客的加入,可以认定是前三个月的客户大浪淘沙剩下的还有购买欲望的老
    客,这时候的复购率比较稳定,在20%左右徘徊。

    这里我们只能说每月有过一次消费记录以上的玩家占有过消费记录玩家人数的百分
    之二十左右。但我们不知道每月具体消费玩家的人数,如果三个月后,消费人数爆
    减,其实对我们的营销是不利的,尽管复购率在一个稳定水平。

    fig, ax = plt.subplots(figsize = (10,4))
    ax.plot(pivoted_counts_transf.count())
    ax.plot(pivoted_counts_transf.sum())
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('用户数(人)', fontproperties=chinese) 
    ax.set_title('每月消费和二次消费以上用户人数', fontproperties=chinese)
    legends = ['消费人数', '二次消费以上人数']
    ax.legend(legends,  prop=chinese, loc = 'upper right')
    

    在这里插入图片描述

    如图所示,三个月后,用户迅速沉淀,前三个月的新客大概在1891正负387左右人数继续消费波动,而二次消费的客户则很稳定,曲线也趋近直线,大概在400人左
    右波动。这部分的客户放到现实中应该是重点维护的优质客户。

    回购率:回购率是某一个时间窗口内消费的用户,在下一个时间窗口仍旧消费的占比。我前一月消费用户1000,后一个月他们中仍有200个消费,贼回购率是20%。由于牵扯两个时间窗口的计算,所以较之复购率稍稍复杂点。

    #为了不跟上图混淆,我们还是建立个新的透视表,虽然内容是一样的
    pivoted_amount = df.pivot_table (values = 'order_dt', index= 'user_id', columns = 'month', aggfunc = 'count').fillna(0)
    #转化数据,有过购买的为1,没有购买的为0
    pivoted_purchase = pivoted_amount.applymap(lambda x: 1 if x>0 else 0)
    pivoted_purchase.head()
    #定义函数,每个月都要跟后面一个月对比下,本月有消费且下月也有消费,则本月记为1,下月没有消费则为0,本月没有消费则为NaN,由于最后个月没有下月数据,规定全为NaN
    def purchase_return(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 pd.Series(status)
    #应用并且绘图    
    pivoted_purchase_return = pivoted_purchase.apply(purchase_return, axis = 1)
    pivoted_purchase_return.head()
    

    在这里插入图片描述
    由于返回的是个序列后列名发生了改变,我们需要重新倒入列名。

    columns = df.month.sort_values().unique()
    pivoted_purchase_return.columns = columns
    ax = (pivoted_purchase_return.sum()/pivoted_purchase_return.count()).plot(figsize = (10,4))
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('百分比(%)', fontproperties=chinese) 
    ax.set_title('十八个月内用户回购率图', fontproperties=chinese)
    

    在这里插入图片描述

    fig, ax = plt.subplots(figsize = (10,4))
    ax.plot(pivoted_purchase_return.count())
    ax.plot(pivoted_purchase_return.sum())
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('用户数(人)', fontproperties=chinese) 
    ax.set_title('每月消费和每月回购用户人数', fontproperties=chinese)
    legends = ['每月消费人数', '每月回购人数']
    ax.legend(legends,  prop=chinese, loc = 'upper right')
    

    在这里插入图片描述

    由图可知,用户的回购率大于复购率,约在30%左右正负五个点波动,看人数分布表则发现回购人数趋近稳定,那么波动则是偶尔月份间的消费人数基数的变动,可能有营销或者淡旺季,但是这部分回购用户的消费行为大抵稳定,应该跟之前每月复购的用户有一定重合,是属于优质用户。
    对回购率和复购率进行综合分析,可以得出,新客的整体质量低于老客,老客的忠诚度(回购率)表现较好,消费频次稍次,这是这个网站的用户消费特征。

    消费行为中的用户分层

    我们按照用户的消费行为,简单划分成几个维度:新用户、活跃用户、不活跃用户、回流用户。
    新用户(new):新用户的定义是第一次消费的用户。
    活跃用户(active):即连续两个时间窗口都消费过的用户。
    不活跃用户(unactive):不活跃用户则是时间窗口内没有消费过的活跃用户,即一二月份都消费过,三月份没消费过。
    回流用户(return):回流用户是在上一个窗口中没有消费,而在当前时间窗口内有过消费。

    def active_status(data):
        status = []
        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
    
    pivoted_purchase_status = pivoted_purchase.apply(lambda x : pd.Series(active_status(x)), axis =1)
    pivoted_purchase_status.columns = columns
    pivoted_purchase_status.head()
    

    这个函数主要分为两部分的判断,以本月是否消费为界。1⃣️本月若没有消费,则判断是不是第一个月,是的话直接返回unreg(不辨别),不是第一个月的话,我们就可以找出前一月标签,前一个月还是不辨别的话,贼返回unreg(不辨别),因为这个月还是没消费,如果前一个月是新课还是活跃用户,还是回流用户,因为这个月都没消费,重新定义为unactive(不活跃用户)。
    2⃣️本月若有消费,则需要判断是不是第一次消费,若是第一月的消费,因为没有前一个月数据,所以直接是new(新客)。接下来就是不是第一个月又有消费的情况了,此时可以找出前一个月的标签,如果前一个月是不活跃,则返回return(回流用户),如果是unreg,则是第一次消费,返回new(新客),剩下的就是前一个月是新客或者是活跃用户了,此时都返回active(活跃用户)。
    应用后的结果为:
    在这里插入图片描述

    #开始计数每个月的各分类用户人数,并作图,unreg不做计数
    pivoted_status_counts = pivoted_purchase_status.replace('unreg', np.NaN).apply(lambda x: pd.value_counts(x))
    pivoted_status_counts
    ax = pivoted_status_counts.fillna(0).T.plot.area(figsize = (12,6))
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('用户数(人)', fontproperties=chinese) 
    ax.set_title('每月各类用户类型占比面积图', fontproperties=chinese)
    

    在这里插入图片描述
    由图可知,黑色的不活跃用户始终是占据大头的,这也跟我们之前的图表结果相符,其次红色代表的活跃用户非常稳定,是属于核心用户,以及紫色的回流用户,这两个分层相加,大抵是当月的消费用户人数的占比,与我们之前的复购率和回购率的表结果一致,这两层的用户大抵接近两千人左右。
    回流占比:某个时间窗口内回流用户在总用户中的占比。
    活跃占比:某个时间窗口内活跃用户在总用户中的占比。

    return_rate = pivoted_status_counts.apply(lambda x: x/x.sum())
    ax = return_rate.loc['return'].plot(figsize = (12,6))
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('百分数(%)', fontproperties=chinese) 
    ax.set_title('每月回流用户占比', fontproperties=chinese)
    
    ax = return_rate.loc['active'].plot(figsize = (12,6))
    ax.set_xlabel('时间(月)', fontproperties=chinese) 
    ax.set_ylabel('百分数(%)', fontproperties=chinese) 
    ax.set_title('每月活跃用户占比', fontproperties=chinese)
    

    在这里插入图片描述
    在这里插入图片描述
    由图可知,用户回流占比在5%~8%之间波动,趋势向下,有客户流失的预警。用户活跃占比在3%~5%间,作为连续消费用户,质量在一定程度上高于回流用户。结合回流用户和活跃用户看,在后期的消费用户中,60%是回流用户,40%是活跃用户,整体质量还好,但是针对这两个分层依旧有改进的空间,可以继续细化数据。

    用户质量

    因为消费行为有明显的二八倾向,我们需要知道高质量用户为消费贡献了多少份额。

    #新建一个对象,按用户的消费金额生序。新增一列,使用cumsum累加函数,逐行计算累计的金额。
    user_amount = df.groupby('user_id').order_amount.sum().sort_values().reset_index()
    user_amount['amount_cumsum'] = user_amount.order_amount.cumsum()
    user_amount.head()
    

    在这里插入图片描述
    通过上面的图,我们可以知道每个用户的ID及其对应的消费金额,以及累加金额。

    #计算出各阶段金额占总金额的百分比
    amount_total = user_amount.amount_cumsum.max()
    user_amount['prop'] = user_amount.amount_cumsum.apply(lambda x: x / amount_total)
    ax = user_amount.prop.plot()
    ax.set_xlabel('人数(人)', fontproperties=chinese) 
    ax.set_ylabel('百分数(%)', fontproperties=chinese) 
    ax.set_title('用户累计贡献金额百分比', fontproperties=chinese)
    

    在这里插入图片描述
    由图我们可以清晰的看到,金额排名靠后的15000名用户才贡献不到20%的销售量,而此次数据集的总用户人数为23569人,我们可以进一步再看,排名靠后的20000名用户,贡献了接近40%的消费金额,也就是说后面的3569人接近贡献了60%的消费金额,如果我们换算成金额/人单位,这后面的3569名客户相当于签名20000名客户的8.4倍!这也反应了在消费领域中,狠抓高质量用户是万古不变的道理。

    用户生命周期

    这里我们定义第一次消费至最后一次消费为整个用户生命。我们需要找出每个用户的第一次消费和最后次消费

    user_purchase = df[['user_id','order_products','order_amount','order_date']]
    order_date_min = user_purchase.groupby('user_id').order_date.min()
    order_date_max = user_purchase.groupby('user_id').order_date.max()
    life_time = (order_date_max-order_date_min).reset_index()
    life_time.describe()
    

    在这里插入图片描述
    由描述可知,所有用户的平均生命周期是134天,中位数是0天,也就是存在一半的用户是第一次消费就是最后次消费,也就是我们前面所说的低质量客户。而最大是544天,相当于我们这个数据集的总天数,说明这用户是从开始到最后都有消费意愿的高质量用户。
    因为数据中的用户都是前三个月第一次消费,所以这里的生命周期代表的是1月~3月用户的生命周期。因为这里数据只截取到了18个月为止,这时间过后,用户仍然会持续消费,所以理论上,用户的平均生命周期还会增长。接下来我们看下直方图的分布,更加直观。

    life_time['life_time'] = life_time.order_date/np.timedelta64(1,'D')
    ax = life_time[life_time.life_time > 0].life_time.hist(bins =100,figsize = (12,6))
    ax.set_xlabel('天数(天)', fontproperties=chinese) 
    ax.set_ylabel('人数(人)', fontproperties=chinese) 
    ax.set_title('二次消费以上用户的生命周期直方图', fontproperties=chinese)
    
    

    由于这里的数据类型是timedelta时间,它无法直接作出直方图,所以先换算成数值。换算的方式直接除timedelta函数即可,这里的np.timedelta64(1, ‘D’),D表示天,1表示1天,作为单位使用的。因为max-min已经表示为天了,两者相除就是周期的天数数字。
    同时绘图的时候我们加上布尔判定,选出两次消费以上的用户,查看他们的分布。

    在这里插入图片描述
    看图我们可以出图像呈双峰结构,部分质量差的用户,虽然消费了两次,但是仍旧无法持续,此时若想提高点用户转化率,应在用户首次消费30天内应该尽量引导,不然就会流失。少部分用户集中在50天~300天,属于普通型的生命周期,有一定忠诚度。高质量用户的生命周期,集中在400天以后,这时候途中人数又逐渐上升,这已经属于高忠诚用户了,尽量维护好这批高质量用户。
    消费两次以上用户的生命周期接近消费只有一次用户的两倍,所以如何在用户首次消费后进行有效的引导促使其多次消费,可以有效的提高用户的生命周期和用户质量。

    len(life_time[life_time.life_time > 400])
    

    我们同时计算了用户生命周期大于400天的人数,为3651人,跟我们之前的高贡献率人数非常接近,暗示我们这批人应该接近同一批人,也就是说消费金额高的用户往往他们的生命周期也越长,这也符合我们的常规认识。

    这里做个相关性。

    留存率

    留存率也是消费分析领域的经典应用。它指用户在第一次消费后,有多少比率进行第二次消费。与回流率不同,留存率倾向于计算第一次消费,并且可以跨越多个时间窗口。

    #链接两表
    user_purchase_retention = pd.merge(left = user_purchase, right = order_date_min.reset_index(), how = 'inner', on = 'user_id', suffixes=('', '_min'))
    user_purchase_retention['order_date_diff'] = user_purchase_retention.order_date-user_purchase_retention.order_date_min
    user_purchase_retention['date_diff'] = user_purchase_retention.order_date_diff.apply(lambda x: x/np.timedelta64(1,'D'))
    user_purchase_retention.head()
    

    这里用到merge函数,它和SQL中的join差不多,用来将两个DataFrame进行合并。我们选择了inner 的方式,对标inner join。即只合并能对应得上的数据。这里以on=user_id为对应标准。这里merge的目的是将用户消费行为和第一次消费时间对应上,形成一个新的DataFrame。suffxes参数是如果合并的内容中有重名column,加上后缀。
    然后将order_date和order_date_min相减。获得一个新的列,为用户每一次消费距第一次消费的时间差值,然后在整除np.timedelta64(1,‘D’)来获得日期差数值。
    在这里插入图片描述
    然后将时间差值分桶。我这里分成0~3天内,3~7天内,7~15天等,代表用户当前消费时间距第一次消费属于哪个时间段呢。这里date_diff=0并没有被划分入0~3天,因为计算的是留存率,如果用户仅消费了一次,留存率应该是0。另外一方面,如果用户第一天内消费了多次,但是往后没有消费,也算作留存率0。

    bin = [0,30,60,90,120,150,180,365]
    user_purchase_retention['date_diff_bin'] = pd.cut(user_purchase_retention.date_diff, bins = bin)
    
    pivoted_retention= user_purchase_retention.groupby(['user_id','date_diff_bin']).order_amount.sum().unstack()
    pivoted_retention.head()
    

    在这里插入图片描述
    直接用金额表达不出留存率,我们还是按照之前的算法,把消费过的转换成1,未消费过的转换成0,毕竟留存率看的是是否有消费。

    pivoted_retention_trans = pivoted_retention.fillna(0).applymap(lambda x: 1 if x >0 else 0)
    ax = (pivoted_retention_trans.sum()/pivoted_retention_trans.count()).plot.bar()
    ax.set_xlabel('时间跨度(天)', fontproperties=chinese) 
    ax.set_ylabel('百分数(%)', fontproperties=chinese) 
    ax.set_title('各时间段的用户留存率', fontproperties=chinese)
    

    在这里插入图片描述
    有图我们可以清晰的发现,第一个月的留存率高达46%,第二个月就下降到35%左右,之后几个月逐渐趋近稳定在25%左右,说明后面的用户逐渐开始稳定下来,说明通过用户在前三个月的使用中,逐渐开始喜爱本店铺的业务或者转换别家的店铺,所以这时候流失率会增大。从运营的角度来看,留存的玩家都是至少消费两次以上的玩家,比起拉新用户来讲,如何提高这些已消费玩家的持续消费是运营的重点,有些活动还是营销,最好放在前三个月,特别是第一个月来进行比较好。为了更好的确定营销的最好时机,我们来看看用户的平均购买周期。

    平均购买周期

    平均购买周期:用户的两次消费行为的时间间隔。

    #创建函数,返回时间差
    def diff(group):
         = group.date_diff - group.date_diff.shift(-1)
        return d
    last_diff = user_purchase_retention.groupby('user_id').apply(diff)
    ax = last_diff.hist(bins = 20)
    ax.set_xlabel('时间跨度(天)', fontproperties=chinese) 
    ax.set_ylabel('人数(人)', fontproperties=chinese) 
    ax.set_title('用户平均购买周期直方图', fontproperties=chinese)
    

    在这里插入图片描述
    如图所示,典型的长尾分布,大部分用户的消费间隔确实比较短。不妨将时间召回点设为消费后立即赠送优惠券,消费后10天询问用户CD怎么样,消费后30天提醒优惠券到期,消费后60天短信推送。这便是数据的应用了。

    展开全文
  • (2)用户个体消费行为分析 用户消费金额和消费总数的描述统计 用户消费金额和消费总数的散点图 用户消费金额和消费总数的分布图 用户累计消费金额的占比 (3)用户消费行为分析 用户第一次消费时间(用户首次...
  • 奢侈品消费群体的消费行为分析——以LV路易威登为例
  • 数据分析项目实战之用户消费行为分析

    万次阅读 多人点赞 2019-07-23 14:38:50
    数据分析项目中固然是用到很多的数据分析工具和技巧,但是业务知识也占比不小,本案例分析了来自CDNow网站的一份用户购买CD明细,业务结合技术进一步分析用户的消费行为,提高决策质量。CD数据包括用户ID,购买日期...
  • 大学生消费行为分析基于消费者行为的秒杀现象探讨毕业论文.doc
  • 每月消费总金额 每月的消费次数(订单数) 每月的产品购买量 每月的消费人数(去重)​ 用户消费行为分析 用户第一次消费(首购) 用户最后一次消费 新老客的消费比 用户分层 用户质量 用户生命周期 用户购买周期 ...
  • 这里只进行用户消费行为分析,主要来认识是用户在总体和个体上的消费情况,从大到小,对用户的消费质量有一个更深的认识,利于后续的精准运营策略设计。 二、分析步骤 2.1数据预处理 数据的提取、清洗、转换 2.2用户...
  • 网络营销网上消费行为分析.ppt
  • 在为师生提供优质、高效信息化服务的同时,系统自身也积累了大量的历史记录,其中蕴含着学生的消费行为以及学校食堂等各部门的运行状况等信息。 很多高校基于校园一卡通系统进行“智慧校园”的相关建设,例如《扬子...
  • 数据分析实战之用户消费行为分析

    千次阅读 2020-07-15 14:53:29
    本次主要根据淘宝用户的行为数据,分析挖掘有价值的信息,通过数据清洗、数据分析、数据可视化、最后结合使用相关算法模型挖掘数据价值,从而为营销提供相应的数据支撑 二、数据来源 本次使用的数据来源于阿里天池...
  • 农村居民超市消费行为分析,沙敏,冯委丽,本文以问卷调查数据为基础,选择商品质量、个人及家庭特征、年人均收入和村杂货铺数量等为解释变量,利用Probit 模型建立农村居民�
  • 以秦路老师的数据分析课程的CDNow用户消费案例为参考,对该健身平台的用户进行消费特征分析分析框架如下: 1. 描述性统计 从数据的描述性统计中可以看出,会员用户每次消费平均购买1.47个商品,每次平均消费22....
  • 针对女性消费群体的消费行为分析的产品设计;一手机调查分析;市场竞争状况;手机市场发展趋势;二消费者行为分析;二消费者购买行为过程分析;2消费者的价位选择;3消费者购机的功能偏好 ;三女性市场调查分析(2) 消费心理...
  • 试谈牛奶消费与消费行为分析思路.pptx

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 93,390
精华内容 37,356
关键字:

消费行为分析

友情链接: LFM_Keygen.rar