CDNow用户消费行为分析

数据集来自:http://www.brucehardie.com/datasets/

工具:jupyter,python

 

一、项目背景

CDNow曾经是一家在线音乐零售*台,后被德国波泰尔斯曼娱乐集团公司出资收购,其资产总价值在最辉煌时曾超过10亿美元。本文主要通过分析CDNow网站的用户购买明细来分析该网站的用户消费行为,使运营部门在营销时更加具有针对性,从而节省成本,提升效率

 

二、主要从以下方面进行分析

1、用户整体消费分析

2、用户个人消费分析

3、用户消费周期分析

4、用户分层:RFM模型

 

三、分析过程

3.1 导入数据

#导入需要的库
import pandas as pd 
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
plt.style.use('ggplot')
plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签
plt.rcParams['axes.unicode_minus']=False #显示负数

#导入数据
columns = ['用户ID','购买日期','订单数','订单金额']
df = pd.read_table('CDNOW_master.txt',names = columns,sep = '\s+')

#查看前五行
df.head()

  • 需要注意的是,原数据集没有表头,所以在导入时自定义表头名称
  • 观察数据,数据中存在一个用户在同一天或不同天下多次订单的情况,如用户ID为2的用户就在1月12日买了两次

 

3.2 数据清洗

3.2.1 查看数据情况,观察数据是否有空值

df.info()

 

 从结果可以看到原始数据没有空值,同时注意到购买日期的字段类型是int64,不是时间类型,后续的处理需要进行类型转换

 

3.2.2 查看是否有重复值

df[df.duplicated() == True]

 

 可以看到存在255条重复数据,将这些重复值删去

df = df.drop_duplicates()

#查看是否删除成功
df.info()

 

从结果可以看到重复数据已经删去

 

3.2.3 对购买日期字段转换类型

df['购买日期'] = pd.to_datetime(df.购买日期,format = '%Y%m%d') #Y四位数的日期部分,y表示两位数的日期部分
df['月份'] = df.购买日期.values.astype('datetime64[M]') 

df.head()

 

  •  astype也可以将时间格式进行转换,比如[M]转化成月份。这里将月份作为消费行为的主要事件窗口
  • 至此数据处理结束

 

3.3 描述性统计

#对订单数和订单金额做描述性统计
df[['订单数', '订单金额']].describe()

 从describe描述统计中可以看出:

  • 用户每个订单*均购买2.41个商品,每个订单*均消费35.96元 
  • 关于订单数,标准差为2.34,说明数据具有一定的波动性;中位数为2个商品,75分位数为3个商品,说明大部分订单的购买数量都不多;最大值在99个,数字比较高
  • 订单金额和订单数情况类似,大部分订单都集中在小额,少部分订单金额极高
  • 一般而言,消费类的数据分布,都是长尾形态。大部分用户都是小额,而小部分用户贡献了收入的大头,俗称二八。初步判断CDNow网站消费符合二八分布

 

3.4 用户总体消费趋势分析

# 设置图的大小,添加子图
plt.figure(figsize=(20,15))
# 每月的总销售额 plt.subplot(221) df.groupby('月份')['订单金额'].sum().plot(fontsize=24) plt.title('总销售额',fontsize=24) #每月的消费次数 plt.subplot(222) df.groupby('月份')['购买日期'].count().plot(fontsize=24) plt.title('消费次数',fontsize=24) #每月的销量 plt.subplot(223) df.groupby('月份')['订单数'].sum().plot(fontsize=24) plt.title('总销量',fontsize=24) #每月的消费人数 plt.subplot(224) df.groupby('月份')['用户ID'].apply(lambda x:len(x.unique())).plot(fontsize=24) plt.title('消费人数',fontsize=24) plt.tight_layout() # 设置子图的间距
plt.show()

 

 

 

 

 

 

 

 

 

 

 

 

  • 四个折线图的整体趋势基本一致,可以看出来,1997年前3个月的销量特别高,随之而来的销售额也是暴涨,在3月份之后骤然下降,接**稳
  • 为什么会呈现这个原因呢?假设是用户身上出了问题,早期时间段的用户中有异常值,第二假设是各类促销营销,但这里只有消费数据,所以无法判断
  • 另一方面,在2月到3月这段期间,可以发现消费人数稍有下降,但总销量与总销售额却依然上升,或许意味着3月份的用户中有需要重点发展的高价值客户

 

3.5 用户个体消费趋势分析

3.5.1 用户消费金额和消费次数的描述统计

#对用户进行分组
group_user = df.groupby('用户ID').sum()

group_user.describe()

  • 从用户角度看,每位用户*均购买7张CD,最多的用户购买了1033张。
  • 用户的*均消费金额100元,标准差是240;*均值和75分位接*,肯定存在小部分的高额消费用户,这部分用户拉高了*均值,这也符合二八法则

 

3.5.2 用户消费金额与消费次数的规律

#绘制散点图。查询条件:订单金额小于5000
group_user.query('订单金额 < 5000').plot.scatter(x='订单金额',y='订单数')

 绘制用户的散点图,用户比较健康而且规律性很强。因为这是CD网站的销售数据,商品比较单一,金额和商品量的关系也因此基本呈线性关系,离群点较少

 

3.5.3 用户消费金额的直方图(观察二八分布)

group_user['订单金额'].plot.hist(bins = 20)

  • 从图上看出,用户的消费呈集中趋势,可能是有个别的极大值干扰导致
  • 可以排除极大值再看看分布情况
#查询条件:订单金额小于1000
group_user.query("订单金额 < 1000")['订单金额'].plot.hist(bins=20)

 

对数据进一步探索,

#高消费用户数。因为已经对用户分组,所以求订单数的次数就是用户数
print('高消费用户数:',group_user[group_user['订单金额']>200]['订单数'].count())
#高消费用户贡献的销售额
print('高消费用户贡献的销售额:',group_user[group_user['订单金额']>200]['订单金额'].sum())
#全部用户的消费金额 print('总消费金额:',group_user['订单金额'].sum())

 

 从上述结果可以看到:

  • 大部分用户的消费能力并不高,消费50元以下的用户超过12000人,超过总用户数50%;
  • 高消费用户( >200元 )不超过3000人,约占总用户数12.7%,但这部分用户贡献的销售额约占总销售额56%;
  • 虽然存在高消费用户群,但是大部分的用户还是集中在比较低的消费档次

 

3.5.4 用户消费次数的分布图

group_user.query('订单数 < 100').订单数.hist(bins = 40)

 

  • 大部分用户购买CD的数量都是在3张以内,购买大量CD的用户数量并不多

 

3.6 用户消费周期分析

3.6.1 用户购买周期

#每个用户的购买时间间隔
order_diff = df.groupby('用户ID').apply(lambda x:x['购买日期'] - x['购买日期'].shift())

order_diff.head(10)

order_diff.describe()

 

  • *均每个用户的购买时间间隔是69天,间隔最长的是533天。想要召回用户,在60天左右的消费间隔是比较好的;
  • 绝大部分用户的消费周期都低于100天

 

3.6.2 用户消费周期分布

plt.figure(figsize=(15,5))
plt.hist((order_diff / np.timedelta64(1, 'D')).dropna(), bins = 50)
plt.xlabel('消费周期',fontsize=24)
plt.ylabel('频数',fontsize=24)
plt.title('用户消费周期分布图',fontsize=24);

  • 大部分用户的消费周期比较短,可以考虑在消费者完成购买行为后30天左右发放优惠券,鼓励用户再次消费

 

3.6.3 用户生命周期

#消费的最后一天减去第一天得周期
orderdt_min=df.groupby('用户ID').购买日期.min()#第一次消费
orderdt_max=df.groupby('用户ID').购买日期.max()#最后一次消费

(orderdt_max-orderdt_min).head()

#用户*均生命周期
(orderdt_max-orderdt_min).mean()

  •  *均生命周期134天,这个值还是很高的,考虑到高消费用户群的存在,看看生命周期分布
((orderdt_max-orderdt_min)/np.timedelta64(1,'D')).hist(bins=15)

 

从直方图看:

  • 大部分用户只消费了一次,即生命周期集中在0天
  • 消费了一次以上的老客看起来生命周期分布较均匀,接下来可以单独看老客的分布

 

#计算所有消费过两次以上的老客的生命周期
life_time = (orderdt_max - orderdt_min).reset_index()

plt.figure(figsize=(10,5))
life_time['life_time'] = life_time.购买日期 / np.timedelta64(1,'D')
life_time[life_time['life_time'] > 0]['life_time'].hist(bins = 100, figsize = (12,6))

 

从直方图看:

  • 用户生命周期呈现双峰趋势,20天内生命周期的用户是一个高峰,400至500天内生命周期的用户是另一个高峰
  • 根据此情况,应该在20天内对客户进行引导,促进其再次消费并形成消费习惯,延长其生命周期;在100至400天的用户,也要根据其特点推出有针对性的营销活动,引导其持续消费

 

3.7 用户分层-RFM模型

rfm = df.pivot_table(index = '用户ID',
                     values = ['订单金额','购买日期','订单数'],
                     aggfunc = {'订单金额':'sum',
                                '购买日期':'max',
                                '订单数':'sum'})

# 日期的最大值与当前日期的差值为R
rfm['R'] = (rfm['购买日期'].max() - rfm['购买日期']) / np.timedelta64(1,'D')
rfm.rename(columns = {'订单金额':'M',
                     '订单数':'F'},
           inplace=True)

# 构建rfm模型公式
def get_rfm(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
rfm['label'] = rfm[['R','F','M']].apply(lambda x:(x-x.mean()) / x.std()).apply(get_rfm,axis=1)
#求和 rfm.groupby('label').sum()

 

可以看到重要保持客户的消费金额是最高的

 

#统计各层次用户数
rfm.groupby('label').size()

 

 可以看到,一般挽留用户的消费人数排名第一,有14074人,重要保持客户排名第二,有4554人,与一般挽留用户差距比较大,但累计消费金额最多,业务方可以根据结果对客户分类运营,降低营销成本,提高ROI

 

posted @ 2020-10-03 22:35  Cles  阅读(477)  评论(0)    收藏  举报