Cles

数据集来自: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

 

分类:

技术点:

相关文章: