本文是对CD案例的一个总结,主要是根据用户消费记录,分析用户消费行为,建立RFM模型,分析复购率、回购率等关键指标。希望对其他产品的线上消费数据分析有一定的借鉴价值。
分析过程
- 准备工作(数据集观察与数据清洗)
- 用户消费趋势分析(按月)——每月消费总金额、消费次数、产品购买量、消费人数、用户平均消费金额、用户平均消费次数
- 用户个体消费分析——用户消费金额,产品购买量的描述性统计、用户消费金额和产品购买量分布、用户累计消费金额占比
- 用户消费行为分析——用户第一次消费(首购)时间分布、用户最后一次消费时间分布、新老用户占比、用户分层RFM模型、各类用户(新用户、活跃用户、流失用户、回流用户)数量和占比、用户购买周期、用户生命周期
- 用户复购率和回购率分析——复购率、回购率
一丶数据集观察与数据清洗
1.1 导入数据集
数据集为txt文件格式,没有列名,并且字段之间使用多个空格进行分隔。
这里读取文件时使用sep=’\s+’,如果在分隔符里存在多个字符串,可以用s+,+类似于正则匹配,无论分隔符有多少个空格都可以自动处理。
path = r'D:\yl\project'
os.chdir(path)
columns = ['user_id','order_dt','order_products','order_amount']
df = pd.read_table('CDNOW_master.txt',names = columns,sep = '\s+')
1.2 数据清洗
检查数据,发现数据集不存在缺失值,但是order_dt数据类型为int64,需要转换为日期型datetime64[ns]。
由于接下来需要按月分析用户消费趋势,这里新建一个month字段。将order_dt列转换为datetime64[M],默认会是每月的第一天。同理,如果设置为datetime64[Y]就是每年的1月1日。
df['order_dt']=pd.to_datetime(df.order_dt,format="%Y%m%d")
df['month']=df.order_dt.values.astype('datetime64[M]')
二丶用户消费趋势分析(按月)
2.1 每月的消费总金额
grouped_month=df.groupby('month')
order_month_amount=grouped_month.order_amount.sum()
order_month_amount.plot(figsize=(16,9))
消费金额在前三个月达到最高峰,后续消费较为稳定,有轻微下降趋势。
2.2 每月的消费次数
grouped_month.user_id.count().plot()
前三个月产品购买量最大,达到20000甚至以上,后续月份产品购买量较为稳定,平均7000左右。
2.3 每月的消费人数
# 这里 x 其实是一个数组,是每月分组的用户id,去重后求数组的 len 长度就代表每月的用户数
df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates())).plot()
每月消费人数低于每月消费次数,但差异不大。
前三个月每月的消费人数在8000-10000之间,后续月份,平均消费人数在2000不到。
2.4 数据透视表
上面进行的汇总分析,其实可以用数据透视的方法更快实现,一次求出每月的消费总金额、每月的消费次数、每月的产品购买量。
df.pivot_table(index = 'month',values = ['order_products','order_amount','user_id'],\
aggfunc = {
'order_products':sum,'order_amount':sum,'user_id':pd.Series.nunique})
三丶用户个体消费分析
3.1 用户消费金额和产品购买量的散点图
grouped_user.sum().plot.scatter(x='order_amount',y='order_products')
绝大部分的数据集中分布,小部分极值对分析有一定的干扰。
可以使用query方法,筛选出order_amount<4000的用户,排除极值的干扰。
grouped_user.sum().plot.scatter(x='order_products',y= 'order_amount',figsize=(16,9))
用户消费金额与产品购买量几乎成线性关系,购买的商品越多,消费金额越大。
3.2 用户消费金额的分布图
grouped_user.sum().order_amount.plot.hist(bins=20)
用户消费金额,绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常。
grouped_user.sum().query