项目背景
CDNOW是美国的一家网上唱片公司,成立于1994年,后来被贝塔斯曼音乐集团收购。
数据来源
本次分析的数据来源是CDNow网站在1997年1月1日至1998年6月30日期间的用户消费数据。数据集一共有用户ID,购买日期,购买数量,和购买金额四个字段。
分析目标
通过对网站的用户消费行为进行分析,得出用户消费行为能力,建立RFM模型,分析复购率、回购率等关键指标结果,以便更清楚了解用户,为进一步的营销策略提供依据。
目录:
一、导入数据
二、查看数据基本信息
三、时间数据类型转换
四、用户消费趋势分析
--4.1每月的总销售额
--4.2每月的销量
--4.3每月消费次数
--4.4每月消费人数
--4.5每月用户平均消费金额
--4.6每月用户平均消费次数
五、用户个体消费数据分析
--5.1用户购买金额、购买数量的描述性统计
--5.2用户购买金额、购买数量的散点图
--5.3用户购买金额的分布图
--5.4用户购买数量的分布图
--5.5用户累计消费金额占比
六、用户生命周期
--6.1用户第一次消费时间分布
--6.2用户最后一次消费时间分布
--6.3用户生命周期的描述
--6.4用户生命周期的分布
七、用户消费周期(用户的每次购买时间间隔)
--7.1用户消费周期的描述
--7.2用户消费周期的分布
八、用户分层
--8.1按用户价值分层——RFM模型
--8.2按用户活跃程度分层——新用户、活跃用户、不活跃用户、回流用户数量和占比
九、复购率和回购率分析
--9.1多少用户仅消费一次
--9.2每月新用户占比
--9.3复购率
--9.4回购率
十留存率
--10.1留存率计算
--10.2计算各个时间段内再次购买的用户占总用户的比重
十一、小结
一、导入数据
import pandas as pd
columns=['user_id','order_dt','order_products','order_amount'] #表头为用户ID,购买日期,购买数量,购买金额
df=pd.read_csv('CDNOW_master.txt',names=columns,sep='\s+')
加载包和数据,文件是txt,用read_csv方法打开,因为原始数据不包含表头,所以需要赋予。字符串是空格分割,用\s+表示匹配任意空白符。
二、查看数据基本信息
print(df.head())
out:
查看数据的前五行。
print(df.info())
out:
数据共4列,每列有69659个非空值,购买金额数据类型为浮点数,其他为整数。没有缺失值,所以不用进行缺失值的处理。
print(df.describe())
out:
最大购买数量为99个,最小为1个,最大购买金额为1286.01,最小为0。每个订单平均购买2.41个商品,平均消费35.89元。
三、时间数据类型转换
df['order_dt']=pd.to_datetime(df['order_dt'],format='%Y%m%d')
df['month'] = df.order_dt.values.astype('datetime64[M]')
print(df.head())
out:
因为之前购买时间列数据类型为整数,所以把它变成时间类型。添加新列 month,对order_dt列(取values),转换类型为datetime64[M],默认是每月的第1天。
四、用户消费趋势分析(按月)
4.1每月的总销售额
ze=df['order_amount'].groupby(df['month']).sum()
print(ze)
out:
#绘制折线图
import matplotlib.pyplot as plt #加载可视化包
plt.style.use('ggplot') #更改设计风格
ze.plot()
plt.show()
由上图可知,销售额在前3个月持续增长,在第3个月达到最高峰,接近40万元,后续消费额较为稳定,有轻微下降趋势。
4.2每月的销量
xl=df['order_amount'].groupby(df['month']).sum()
xl.plot()
plt.show()
销量同销售额一样,销量在前3个月持续增长,在第3个月达到最高峰,超过25000,后续销量较为稳定,有轻微下降趋势。
4.3每月消费次数
cs=df['order_dt'].groupby(df['month']).count()
cs.plot()
plt.show()
购买次数在前3个月持续增长,在第3个月达到最高峰,接近12000,后续稳定在每月3000左右。
4.4每月消费人数
rs=df['user_id'].groupby(df['month']).apply(lambda x:len(x.unique()))
rs.plot()
plt.show()
前3个月每月的消费人数在8000-10000之间,后续月份的平均消费人数稳定在2000左右。
4.5每月用户平均消费金额
zee=ze/rs
zee.plot()
plt.show()
每月用户平均消费金额都在37.5元以上,1997年1月份最低,1998年11月最高,约为57元。
4.6每月用户平均消费次数
css=cs/rs
css.plot()
plt.show()
每月用户平均消费次数都在1次以上
五、用户个体消费数据分析
5.1用户购买金额、购买数量的描述性统计
mg=df.groupby(df['user_id']).sum() #统计每个用户的购买金额和购买数量
print(mg.describe())
out:
从用户角度看,平均每位用户购买7张CD,中位数为 3 张,平均数大于中位数,说明小部分用户购买了大部分的CD。平均每个用户消费106元,中位数为43元,说明高额消费用户集中在小部分用户中。
5.2用户购买金额、购买数量的散点图
mg.plot.scatter(x='order_amount',y='order_products')
plt.show()
绝大部分的数据集中分布,小部分极值对分析有一定的干扰。可以使用query方法,筛选出order_amount<4000的用户,排除极值的干扰。
mg.query('order_amount<4000').plot.scatter(x='order_amount',y='order_products')
plt.show()
由散点图可知,用户购买金额和购买数量基本呈线性关系,购买数量越多,购买金额越高。
5.3用户购买金额的分布图
mg.order_amount.plot.hist(bins=20)
plt.show()
从图上可以看出,用户的消费金额绝大部分呈现集中趋势,可能是有个别的极大值干扰了判断,可以使用query过滤操作排除极值。
mg.query('order_products<100').order_amount.plot.hist(bins=20)
plt.show()
可以看出,大多数用户消费金额并不高,大部分不超过200元。
一点说明,根据切比雪夫定理,所有数据中至少有96%的数据位于平均数5个标准差之内,剩下4%的极值就过滤掉。这里以order_products作为过滤条件,购买数量的均值为7.12,标准差为16.98,7.12+5*16.98=92.02,所以选择100作为阈值。
5.4用户购买数量的分布图
mg.query('order_products<100').order_products.plot.hist(bins=20)
plt.show()
大部分用户购买数量并不高,一般不超过20个,超16000位用户购买数量为0-5个。
5.5用户累计消费金额占比
mgj=df['order_amount'].groupby(df['user_id']).sum().sort_values()
ljx=mgj.cumsum()/mgj.sum()
print(ljx)
out:
ljx.reset_index(drop=True).plot() # reset_index()重置索引是为了得到一个自然数的行标签
plt.show()
横坐标表示用户数量(总共有23570名用户),纵坐标表示累计消费金额占比。可以看出,排名前3000的用户贡献了近60%的消费总金额,这也反映出了二八法则。
六、用户生命周期
6.1用户第一次消费时间分布
df['order_dt'].groupby(df['user_id']).min().value_counts().plot()
plt.show()
可以看出,用户第一次购买时间主要集中在前三个月。其中,在2月5日到2月25日之间有剧烈的波动。
6.2用户最后一次消费时间分布
df['order_dt'].groupby(df['user_id']).max().value_counts().plot()
plt.show()
用户最后一次购买的时间分布范围较广,大部分用户的最后一次购买时间集中在前3个月,说明这部分用户只购买了一次,忠实用户较少。出现断崖式下跌很正常,一开始用户数量迅猛增长,流失的也比较多。
6.3用户生命周期的描述
user_life=df['order_dt'].groupby(df['user_id']).max()-df['order_dt'].groupby(df['user_id']).min()
print(user_life.describe())
结果表明,用户平均生命周期为 134 天;用户生命周期中位数仅为 0 天,说明一半以上用户仅消费1次,这部分用户属于低质量用户;用户最大生命周期为 544 天,差不多一年半的时间,和数据集时间相近,该用户属于重要客户。
6.4用户生命周期的分布
(user_life/np.timedelta64(1,'D')).hist(bins=40)
plt.show()
因为数据类型是timedelta时间,无法直接作出直方图,所以先换算成数值。换算的方式直接除timedelta函数即可,np.timedelta64(1, ‘D’),D表示天,1表示1天,作为单位使用。
生命周期为0,即仅消费1次的用户对结果分布影响较大,可以将这部分用户筛选掉。
life=user_life/np.timedelta64(1,'D')
life[life>0].hist(bins=40)
plt.show()
print(life[life>0].describe())
排除掉生命周期为0的用户后,用户生命周期呈现双峰趋势,20天内生命周期的用户是一个高峰,400至500天内生命周期的用户是另一个高峰。根据此情况,应该在20天内对客户进行引导,促进其再次消费并形成消费习惯,延长其生命周期;在100至400天的用户,也要根据其特点推出有针对性的营销活动,引导其持续消费。消费两次以上的用户平均生命周期是 276 天,远高于总体的134天。
七、用户消费周期(用户的每次购买时间间隔)
7.1用户消费周期的描述
order_diff=df.groupby(df['user_id']).apply(lambda x:x.order_dt-x.order_dt.shift())
print(order_diff.describe())
错行相减计算相邻两个订单的时间间隔,shift 函数是对数据进行错位,所有数据会往下平移一位。
平均每个用户的购买时间间隔是68天,间隔最长的是533天。想要召回用户,在60天左右的消费间隔是比较好的。大部分用户的消费周期都低于90天。
7.2用户消费周期的分布
(order_diff/np.timedelta64(1,'D')).hist(bins=20)
plt.show()
可以看出,大部分用户的消费间隔确实比较短。
八、用户分层
8.1按用户价值分层——RFM模型
RFM模型主要通过三个指标对客户价值进行细分:
最近一次消费-R:客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则交易发生的日期越近。
消费频率-F:客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。
消费金额-M:客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
通过这三个指标,将客户细分为八类:
rfm=df.pivot_table(['order_dt','order_products','order_amount'],index='user_id',
aggfunc={'order_dt':'max','order_products':'count','order_amount':'sum'})
使用透视表得出每个用户最后一次消费时间,总交易次数,总交易金额。
rfm['time']=(rfm['order_dt'].max()-rfm['order_dt'])/ np.timedelta64(1, 'D')
print(rfm.head())
因为数据集距今日期太久,所以我们用数据集的最大日期来算用户最后一次消费时间距今日期。
#比较每一项和均值的大小,分出高低(实际工作中RFM的划分标准应该以业务为准)
rfm['r_m']=rfm['time']-rfm['time'].mean()
rfm['f_m']=rfm['order_products']-rfm['order_products'].mean()
rfm['m_m']=rfm['order_amount']-rfm['order_amount'].mean()
def hanshu(x):
if x>0:
return 1
else:
return 0
rfm['r']=rfm['r_m'].apply(hanshu)
rfm['f']=rfm['f_m'].apply(hanshu)
rfm['m']=rfm['m_m'].apply(hanshu)
print(rfm.head())
out:
rfm['jieguo']=rfm['r'].map(str)+rfm['f'].map(str)+rfm['m'].map(str)
ppp={'111':'重要价值客户',
'011':'重要保持客户',
'101':'重要发展客户',
'001':'重要挽留客户',
'110':'一般价值客户',
'010':'一般保持客户',
'100':'一般发展客户',
'000':'一般挽留客户'}
rfm['leixing']=rfm['jieguo'].map(ppp)
print(rfm.head())
out:
#统计不同类型客户的总消费金额、消费次数
asd=rfm.pivot_table(['order_amount','order_products'],index='leixing',aggfunc=sum)
print(asd)
out:
8种客户中,重要保持客户的消费金额和消费次数最高,其次是一般发展客户。
#统计各类用户的人数
print(rfm['leixing'].value_counts())
out:
8种客户中,一般发展客户的人数最多,为13608人,其次是重要保持客户。
8.2按用户活跃程度分层——新用户、活跃用户、不活跃用户、回流用户数量和占比
dff=df.pivot_table(['order_dt'],index='user_id',columns='month',aggfunc='count')
dff.fillna(0,inplace=True)
print(dff.head())
out:
def active_status(data):
status = []
for i in range(18): # 数据一共有18个月份
if data[i] == 0:
if len(status) > 0:
if status[i - 1] == 'unreg': #unreg为未注册
status.append('unreg')
else:
status.append('unactive') #上月有消费,本月没有消费,则为不活跃
else:
status.append('unreg')
else: #若本月消费
if len(status) > 0:
if status[i - 1] == 'unactive':
status.append('return') #上个月不消费,这个月消费了,则为回流用户
elif status[i - 1] == 'unreg':
status.append('new') #上个月未注册,这个月消费了,则为新用户
else:
status.append('active') #上个月消费,这个月也消费,则为活跃用户
else:
status.append('new')
return pd.Series(status)
sdff=dff.apply(active_status,axis=1)
print(sdff.head())
out:
把未注册的替换为空值,这样count不会计算到,得到每个月的用户分布
# 把未注册的替换为空值,这样count不会计算到,得到每个月的用户分布
sdff2=sdff.replace('unreg',np.NaN)
yhfb=sdff2.apply(lambda x:x.value_counts())
print(yhfb)
out:
把null值填充为0,并进行转置
# 把null值填充为0,并进行转置
yhfb=yhfb.fillna(0).T
print(yhfb)
out:
从表中可以看出,新客都是集中在前三个月,第三个月出现回流用户,数量较为稳定,整体在1000左右,活跃用户前四个月较多,后面逐步下降,不活跃用户数量很多,基本上每月都在20000以上。
# 绘制面积图
yhfb.plot.area()
plt.show()
计算每月各类用户占比:
# 计算每月各类用户占比
yhzb=yhfb.apply(lambda x:x/x.sum(),axis=1)
print(yhzb)
out:
九、复购率和回购率分析
9.1多少用户仅消费一次
yici=df['order_dt'].groupby(df['user_id']).count()
yici=yici[yici==1]
print(yici.count())
out:
这表明约一半的用户只消费了一次,留存效果不好。
9.2每月新用户占比
#先找出每个用户消费的最小月份
xx=df['month'].groupby(df['user_id']).min()
print(xx.value_counts())
out:
发现只有前三个月有新用户。
print(xx.value_counts()/df['month'].value_counts()) #再除以每个月的总用户数
out:
所以,前三个月的新用户占比为88%,75%,62%。
9.3复购率
复购率:自然月内,购买多次的用户占比。即一个月内购买两次及以上用户占该月总用户的比率。
#把消费两次及以上记为1,消费一次记为0,其他记为空值,以便于计算复购率
def han(y):
if y>1:
return 1
elif y==1:
return 0
else:
return np.nan
ddf=dff.applymap(han)
print(ddf.head())
out:
fgl=ddf.sum()/ddf.count()
print(fgl)
out:
fgl.plot()
plt.show()
复购率稳定在20%左右,前3个月因为有大量新用户涌入,而这批用户只购买了一次,所以导致复购率较低。
9.4回购率
回购率:是某一个时间窗口内消费的用户,在下一个时间窗口仍旧消费的占比。比如,我1月消费用户1000,他们中有300个2月依然消费,回购率是30%。所以要计算一个月的回购率,要用下一个月依然消费的用户数除以本月的总消费用户数。
#把当月有购买的记为1,无购买的记为0
def hansu(z):
if z>=1:
return 1
else:
return 0
ddff=dff.applymap(hansu)
print(ddff.head())
out:
#如果本月进行消费,下月也进行消费,则记为1;如果下月没有消费,则记为0,若本月没有消费,则记为nan
def han(data):
status=[]
for i in range(17):#循环17个月
if data[i]==1:#若本月消费
if data[i+1]==1:#下个月也消费
status.append(1)#就记为1
if data[i+1]==0:#下个月不消费,就记为0
status.append(0)
else:
status.append(np.nan)
return pd.Series(status)
ddd=ddff.apply(han,axis=1) #axis=1表示计算方向在行的方向上
print(ddd)
out:
#计算回购率
hgl=ddd.sum()/ddd.count()
print(hgl)
out:
hgl.plot()
plt.show()
上图可以看出,初期用户的回购率并不高,前三个月的回购率在15%-20%之间,4月份起回购率大概在30%左右。
十、留存率
10.1留存率计算
#得到用户ID及其下单的时间
df1=df[['user_id','order_dt']].drop_duplicates()
#得到用户ID及其首次下单时间
df2=df['order_dt'].groupby(df['user_id']).min()
#把他们关联起来,得到用户ID,下单时间,首次下单时间
df3=pd.merge(df1,df2,on='user_id')
df3.columns=['user_id','time','mtime'] #修改列名
print(df3.head())
out:
#计算留存率,按最小时间、下单时间分组
df4=df3.pivot_table('user_id',index=['mtime','time'],aggfunc='count')
print(df4)
out:
现在我们已经可以清晰的看到1997-01-01的次日留存率=3/209,三日留存率=3/209,同理可得其他日的n日留存率。
#重置索引
df4=df4.reset_index()
print(df4)
out:
如果我们想看具体某一日的留存率,把它筛选出来就好了
df5=df4[df4['mtime']=='1997-01-01']
print(df5)
out:
10.2计算各个时间段内再次购买的用户占总用户的比重
接下来我们计算每个用户每次下单和首次下单时间的时间差
df3['diff']=df3['time']-df3['mtime'] #计算每次下单时间和首次下单时间的时间差
print(df3.head())
out:
去除时间单位并更改数据类型为整数
df3['diff']=df3['diff'].map(str).str[0:-14] #去除时间单位
df3['diff']=df3['diff'].astype('int64') #更改数据类型
print(df3.head())
out:
将时间差按3天、7天、半个月、一个月、两个月、三个月、半年、一年、两年进行分组
#将时间差按3天、7天、半个月、一个月、两个月、三个月、半年、一年、两年进行分组
bins=[0,3,7,15,30,60,90,180,365,730]
df3['fen']=pd.cut(df3['diff'],bins=bins)
print(df3.head())
out:
计算各个时间段有多少人
df6=df3['fen'].value_counts()
print(df6)
out:
计算各个时间段发生购买的人数占总用户的比重
df7=df6/df['user_id'].drop_duplicates().count()
print(df7)
out:
#绘制柱状图
df7.plot.bar()
plt.show()
只有2.7%的用户在3天内有过再次消费,3.6%的用户在3~7天内有过再次消费。数字并不好看,但CD购买确实不是高频消费行为。有60%的用户在半年后至1年内有过再次购买。
十一、小结
1、用户消费趋势方面,前3个月有大量新用户涌入,销售额、销量、消费次数、消费人数均达到高峰,后续月份较为稳定。销售额在第3个月达到最高峰,接近40万元,后续消费稳定在100000左右。前3个月产品购买量达到20000以上,后续月份平均7000;前3个月消费次数都在10000笔左右,后续月份的平均2500;前3个月消费人数在8000以上,后续月份平均2000左右。
2、用户个体消费方面,小部分用户购买了大量的CD,拉高了平均消费金额。大多数用户消费金额并不高,大部分不超过200元,大约有17000名。大部分用户购买数量并不高,一般不超过20个,超16000位用户购买数量为0-5个。排名前3000的用户贡献了近60%的消费总金额,反映出了消费的二八法则。
3、用户生命周期方面,用户第一次购买时间主要集中在前三个月,大部分用户的最后一次购买时间也集中在前3个月,说明这部分用户只购买了一次,忠实用户较少。用户平均生命周期为 134 天;用户生命周期中位数仅为 0 天,说明一半以上用户仅消费1次,这部分用户属于低质量用户。
4、用户消费周期方面,平均每个用户的购买时间间隔是68天,间隔最长的是533天,最小0天,大部分用户的消费周期都低于90天。
5、从RFM模型来看,8种客户中,重要保持客户的消费金额和消费次数最高,人数排在第二,有4617人;一般发展客户消费频次和消费金额排第二位,人数最多,为13608人。
6、从用户活跃度分层情况来看,新客都是集中在前三个月,第三个月出现回流用户,数量较为稳定,整体在1000左右,活跃用户前四个月较多,后面逐步下降,不活跃用户数量很多,基本上每月都在20000以上。
7、从整体消费记录来看,有一半的用户,只消费了一次。从每月新用户占比来看,只有前三个月有新用户,第一个月新用户占比最高,为88%,第二个月为75%,第三个月为62%。
8、复购率和回购率方面,复购率稳定在20%左右,回购率稳定在30%左右,前3个月因为有大量新用户涌入,而这批用户只购买了一次,所以导致复购率和回购率都比较低。
9、留存率方面,只有2.7%的用户在3天内有过再次消费,3.6%的用户在3~7天内有过再次消费。数字并不好看,但CD购买确实不是高频消费行为。有60%的用户在半年后至1年内有过再次购买。