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

浙公网安备 33010602011771号