CD数据分析

项目简介

这是一份用户消费行为的分析报告
数据来源于网上,是用户在一家CD网站上的消费记录


CD项目数据分析.png

报告目录

字段名
  • user_id:用户ID
    order_dt:购买日期
    order_prodects:购买产品数
    order_amount:购买金额
01 趋势分析
02 用户个体消费分析
03 用户消费行为
04 复购率和回购率分析

观察数据

#导入数据 观察数据
import pandas as pd  
import numpy as np 
columns=['user_id','order_dt','order_products','order_amount']
df_cd=pd.read_table('CDNOW_master.txt',names=columns,sep='\s+')
df_cd.info()
df_cd.describe()
df_cd describe.png
  • 大部分订单只消费了少量商品(平均2.4),有一定值干扰
  • 用户的消费金额比较稳定,平均消费35元,中位数在25元,有一定极值的干扰
#添加月份字段
df_cd['order_dt']=df_cd['order_dt'].apply(lambda x:pd.to_datetime(x,format='%Y%m%d'))
df_cd['year_month']=df_cd['order_dt'].apply(lambda x:str(x)[:7])

01 趋势分析

  • 每月的消费总金额
  • 每月的消费次数
  • 每月的产品购买量
  • 每月的消费人数
  • 每月用户平均消费金额的趋势
  • 每月用户平均消费次数的趋势
from matplotlib import pyplot as plt
%matplotlib inline
grouped_month=df_cd.groupby(['year_month'])
#按月分组聚合
month_amount=grouped_month['order_amount'].sum()
# 每月的消费总金额
month_amount.plot()
用户消费总金额趋势图.png
# 每月的消费次数(订单数)
grouped_month_times=grouped_month['user_id'].count()
grouped_month_times.plot()
月订单数趋势图.png
# 每月的产品购买量
month_sumOrder=grouped_month['order_products'].sum()
month_sumOrder.plot()
用户购买产品量趋势图.png
# 每月的消费人数
month_customerNum=grouped_month['user_id'].apply(lambda x:len(x.drop_duplicates()))
month_customerNum.head()
# 每月用户平均消费金额的趋势
month_avg_cus_amount=month_amount/month_customerNum
month_avg_cus_amount.plot()
用户消费金额趋势图.png
# 每月用户平均购买次数的趋势
month_cus_times=df_cd.groupby(['year_month','user_id'],as_index=False) ['order_products'].count()
avg_cus_times=month_cus_times.groupby(['year_month']).\
  order_products.sum()/  month_cus_times.groupby(['year_month']).order_products.count()
avg_cus_times.plot()
用户平均购买次数趋势图.png

02 用户个体消费分析

  • 用户消费金额,消费次数的描述统计
    按照ID 计数 并describe
grouped_id=df_cd.groupby(['user_id']).sum().reset_index()
grouped_id.describe()

用户平均购买了7张CD,但是中位值只有3,说明小部分用户购买了大量的CD
用户平均消费106元,中位值有43,判断同上,有极值干扰

  • 用户消费金额和消费数量的散点图
plt.scatter(x=grouped_id.order_products,y=grouped_id['order_amount'])
# 用户消费金额,消费数量的关系(散点图)
消费金额和购买数量关系.png
  • 用户消费金额的分布图
    直方图
grouped_id[grouped_id['order_amount']<1800]['order_amount'].plot.hist(bins=10)
# grouped_id.query('order_products<100').order_amount.plot.hist(bins=10)
#直接做直方图,绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常
# 使用切比雪夫定理过滤掉异常值,因为切比雪夫定理说明
# 95%的数据都分布在5个标准差之内,剩下5%的极值就不要了
客户消费金额分布.png

大多数用户购物金额<250元

  • 用户消费次数的分布图
    直方图
df_cd.groupby(['user_id'])[['order_amount']].count().\
  rename(columns={'order_amount':"shopping_times"}).\
query('shopping_times<100').plot.hist(bins=100)
客户消费次数分布.png

只购买过一次的客户占比很大

  • 用户累计消费金额占比(百分之多少的用户占了百分之多少的消费额)
    类似帕累托图
    按照id求和,从小到大排序
    累计求和(百分比) 画图
# 用户累计消费金额占比
grouped_id.sort_values(by='order_amount',inplace=True)
grouped_id['cumsum_prop']=grouped_id.order_amount.cumsum()/grouped_id.order_amount.sum()
grouped_id.reset_index()['cumsum_prop'].plot()
用户累计消费金额占比.png

按照用户消费金额进行升序排序,由图可以知道50%的用户仅贡献了15%的消费额度,而排名前5000的用户就贡献了60%的消费额度

03用户消费行为分析

  • 用户第一次消费(首购)
#首购
df_min=df_cd.groupby('user_id').order_dt.min()
  • 用户最后一次消费
df_max=df_cd.groupby('user_id').order_dt.max()
#最后消费时间
#仅购买一次的客户占比
date_delta[date_delta==0].count()/len(df_min)

一次性消费人数占比.png

50%以上的客户只消费了一次

  • 新老客户消费比
    • 多少用户仅消费一次
    • 每月新客占比
  • 用户分层
    • RFM模型
df_R=df_cd.groupby('user_id').order_dt.agg([max]).reset_index() # 最近一次购买时间 Resently
df_FM=df_cd.groupby(['user_id'])[['order_amount']]\
  .agg(['count','sum']).reset_index() #累计购买次数和购买金额 frequency\monetary
df_RFM=df_R.merge(df_FM,on='user_id') 

# 得到最近一次消费,一般是计算 today 距离最近一次消费,这里因为时间太久远,就用的max值
# 数值越大就越久远,分子得到的是一些天数类似 545 days
#(因为是时间格式相减),除以一个单位,就不会有单位了只留下数值
df_RFM['dt_delta']=-(df_RFM['max']-df_RFM['max'].max())/np.timedelta64(1,'D')
# 重命名,也就是 R:最后一次消费距今天数,F:消费总金额 ,M:消费总产品数
# R :消费时间  F:消费金额  M:消费频次
df_RFM.rename(columns={('order_amount', 'count'):'F',\
('order_amount', 'sum'):'M','dt_delta':'R'},inplace=True)

def RFM(x):
    level=x.apply(lambda x:'1' if x> 0 else '0')
    label=level.R+level.F+level.M
    d={
        # R 为1 表示离均值较远即时间很久,F为1 表示 消费金额比较多,
        #M 为1 表示  消费频次比较多,所以是重要价值客户
        '111':'重要价值客户',
        '011':'重要保持客户',
        '101':'重要发展客户',
        '001':'重要挽留客户',
        '110':'一般价值客户',
        '010':'一般保持客户',
        '100':'一般发展客户',
        '000':'一般挽留客户'
    }
    return d[label]

df_RFM['label']=df_RFM[['R','F','M']].apply(lambda x:x-x.mean()).apply(RFM,axis=1)
df_RFM.loc[df_RFM['label']=='重要价值客户','color']='g'
df_RFM.loc[~(df_RFM['label']=='重要价值客户'),'color']='r'

# 使用分层的结果画图 并将重要价值客户重点标出
df_RFM.plot.scatter('F','R',c=df_RFM.color)
重要价值客户占比.png
df_RFM['label'].value_counts()/len(df_RFM['label'])  #人数占比
df_RFM.groupby('label').sum()/df_RFM.sum() #销售额占比
客户RFM 类别占比及消费额占比.png

从RFM 分层可知,重要保持客户占总客户的20%,却贡献了60% 销售额.
但是这是由于极值的影响,所以 RFM 的划分标准应该以业务为准,也可以通过切比雪夫去除极值后求均值,并且 RFM 的各个划分标准可以都不一样

不要为了数据好看划分等级

  • 用户生命周期
    • 新、老、活跃、回流、流失
# 数据透视, userid为索引,月为列,求每月的消费次数,这里填充了
pivoted_counts=df_cd.pivot_table(index='user_id',
                             columns='year_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.head()
df_purchase.shape[1]
# x是一个list if的多层嵌套
def user_life(x):
    status=[]
    for i in range(18):
        
        if x[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:
                if status[i-1]=='unreg':
                    status.append('new')
                else:
                    if status[i-1]=='unactive':
                        status.append('return')
                    else:
                        status.append('active')
            else:
                status.append('new')
    return status
# 定义用户所处的生命周期的阶段
#使用函数 得出用户所处的阶段
purchase=df_purchase.apply(lambda x:pd.Series(user_life(x)),axis=1)
purchase.columns=df_purchase.columns
purchase.head()
# 这里把未注册的替换为空值,这样 count 计算时不会计算到
# 得到每个月的用户分布
purchase_stats_ct=purchase.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
purchase_stats_ct.T
#面积图(pyecharts)
from  pyecharts.charts import Line
import pyecharts.options as opts
M=purchase_stats_ct.fillna(0).T
c = (
    Line()
    .add_xaxis(M.index.to_list())
    .add_yaxis("active",  M['active'], areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
    .add_yaxis("new", M['new'], areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
    .add_yaxis("return", M['return'], areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
    .add_yaxis("unactive", M['unactive'], areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
    .set_global_opts(title_opts=opts.TitleOpts(title="Line-面积图"))
    )
c.render_notebook()
每月用户分布.png
  • 用户购买周期(按订单)
order_diff1=df_cd.groupby('user_id').apply\
(lambda x:x.order_dt-x.order_dt.shift())/np.timedelta64(1,'D')
order_diff1.hist(bins=[0,10,50,100,200,500,600])
# 每次下单的购买周期
订单周期分布.png
order_diff1.describe()
# 用户平均购买周期 (每个用户每次的购买周期相加/次数)
order_diff1 describe.png

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

  • 用户生命周期分布
date_delta.plot.hist(bins=50)
# 用户生命周期(按第一次和最后一次消费)
date_delta.describe()
date_delta describe.png

用户生命周期分布001.png

用户生命周期分布002.png

用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
用户均消费134天,中位数仅0天

# 购买一次的用户后的分布图
date_delta[date_delta>0].hist(bins=40)

4.复购率和回购率分析[]

  • 复购率
    • 自然月内,购买多次的用户占比(即,购买了两次以上)
# 月内为购买的用户不做数,变成NaN
# 只够买一次的不计数,变为0
pivoted_counts[pivoted_counts == 0]=np.nan
pivoted_counts[pivoted_counts == 1]=0
# 计算复购率 :购买次数>1的人数/月内总人数
repeat_purchase=pivoted_counts.applymap(lambda x: 1 if x>1 else x)
repeat_pur=repeat_purchase.apply(lambda x:x.sum()/x.count())
#复购率趋势图
repeat_pur.plot()
复购率.png
  • 回购率
    • 曾经购买过的用户在某一时期的再次购买的占比(可能是在三个月内)
df_purchase[df_purchase==0]=np.nan
# 定义函数。月内未下单的客户,变成NaN
# 只要购买过的都为1,因此只要本月下单了次月诶呦下单
def binary(data):
    for i in range(0,data.shape[0]):
        for j in range(0,data.shape[1]-1):
            if data.iloc[i,j]==1:
                if data.iloc[i,j+1]!=1:
                    data.iloc[i,j]=0
                
    return data

如果本月购买的人下月也购买了 说明属于本月的回购人群

repurchase=binary(df_purchase)
repurchaseing=repurchase.iloc[:,:17].apply(lambda x:x.sum()/x.count())
repurchaseing.plot()
回购率.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容