项目简介:
淘宝作为中国最大的电商交易平台,每天都在产生海量的用户行为数据,其背后所隐含的信息也值得探索。本项目选取了500w条淘宝用户的行为数据,在所定义问题的基础上,利用Python对数据进行预处理,随后在Python环境中连接MySQL数据库以进行数据分析及可视化,最后在分析的基础上给出了结论及建议。
一、认识数据
1.1 数据来源及介绍
本数据来源于阿里云天池,选择约500万用户在2017年11月25日至12月3日之间发生的行为记录,具有包括点击、购买、加购物车和收藏商品的行为。数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID、行为类型和时间戳组成,并以逗号分隔。
1.2 数据格式与理解

二、提出问题
根据AARRR模型和本次项目的可利用数据类型,提出以下问题进行进一步业务分析:
2.1 用户行为方面
- 页面浏览量PV和独立访客数UV如何变化?和时间有关系吗?
- 用户的平均访问深度是多少?平台的跳失率怎么样?
- 用户从浏览到购买会经历哪些过程?最终的转化率如何?
- 平台用户留存率怎么样?
2.2 用户消费方面
- 平台的用户付费率是多少?用户复购的情况怎么样?
- 平台商品销售情况是怎么样?
- 商品销售之间有没有一定的联系?
2.3 用户价值方面
- 如何判断用户价值?针对不同用户如何采取不同的运营策略?
三、数据处理
#导入相关模块和数据
import pandas as pd
import numpy as np
import time
columns = ['user_id','item_id','category_id','behavior_type', 'timestamp']
df=pd.read_csv(r'C:\Users\ThinkPad\Desktop\User Behavior Data\UserBehavior.csv',names=columns,iterator=True)
df=df.get_chunk(5000000) # 获取500W数据
df.head()


3.1 数据格式的处理
# 先将时间戳转化为日期时间格式并提取时间
from datetime import datetime,timedelta
df['timestamp']=pd.to_datetime(df.timestamp, unit='s')+timedelta(hours=8)
df['date']=df['timestamp'].apply(lambda x:x.date())
df['time']=df['timestamp'].apply(lambda x:x.time())
df['hour']=df['timestamp'].apply(lambda x:x.hour)
weekday=[]
for i in df['timestamp']:
weekday.append(i.weekday())
df['weekday']=weekday

3.2 数据清洗

好像并没有缺失值的样子
再看一下重复值

重复值还是有的,我们删掉他吧
# 删除重复数据
df.drop_duplicates(inplace = True)
df.reset_index()
df.head()
我们再来看看异常值,观察date发现不一般,竟然有2037年和1970年呐,像这种明显不在我们规定的日期里数值,都统统删除。

# 找到比2017-11-25小的数据并删掉
import datetime
start_time=datetime.datetime.strptime('2017-11-25',"%Y-%m-%d")
start_date=datetime.datetime.date(start_time)#df['date']是datetime.date类型,经strptime方法后start_time是datetime.datetime类型,不能直接比较
df=df[df['date']>=start_date]
# 找到比2017-11-25小的数据并删掉
import datetime
end_time=datetime.datetime.strptime('2017-12-03',"%Y-%m-%d")
end_date=datetime.datetime.date(end_time)
df=df[df['date']<=end_date]

好了,到这一步准备工作完毕,这个df以后会经常用到
四、数据分析
(一)用户行为习惯分析
4.1.1 页面访问量PV和独立访客数UV
pv=df.groupby('date')['user_id'].count()
uv=df.groupby('date')['user_id'].apply(lambda x: x.drop_duplicates().count())
pv_uv_rate=pv/uv
pv_uv_daily=pd.DataFrame({'pv':pv,'uv':uv,'pv_uv_rate':pv/uv}).reset_index()
pv_uv_daily

利用tableau进行可视化输出:

从图可以看出pv和uv整体变化趋势相同,11月25日到12月1日之间,uv变化不明显,pv在11月26日达到小高峰,与当天刚好是周六放假密切相关。从12月1日周四开始,pv和uv涨幅明显,12月2日和12月3日与上周相比较,环比增长率31.4%,uv环比增长率35.7%,可见本次活动宣传和引流效果不错,对实际销售情况的影响将在下个模块分析。
接下来,我们按小时来分析用户行为
pv=df.groupby('hour')['user_id'].count()
uv=df.groupby('hour')['user_id'].apply(lambda x: x.drop_duplicates().count())
pv_uv_rate=pv/uv
pv_uv_hour=pd.DataFrame({'pv':pv,'uv':uv,'pv_uv_rate':pv/uv}).reset_index()
pv_uv_hour.head()
得到下表:

可视化后得到下图:

从上图可以看出用户的活跃时间从上午6点开始活跃,10点开始趋于稳定,18点开始呈现明显上升趋势。这符合大多数人的日常作息规律。由此可以建议店铺调整客服工作时间,增加18点到22点的客服数量,促使用户从浏览向购买转换。
4.1.2 平均访问深度和跳失率
# 计算总用户数量
user_count=len(df.user_id.unique())
# 计算总的页面浏览数量
pv_count=df[df.behavior_type=='pv'].shape[0]
print('用户浏览的平均访问深度是 %.1f' % (pv_count/user_count))
用户浏览的平均访问深度是 91.3
#每个不同id的用户浏览页面数
pv_count_perUser=df[df['behavior_type']=='pv'].groupby('user_id')['behavior_type'].count().reset_index().rename(columns={'behavior_type':'pv_count'})
pv_count_perUser.head()
# 计算只浏览过一次界面的用户数量
bounce_user_count=pv_count_perUser[pv_count_perUser['pv_count']==1].shape[0]
#跳失率
print('跳失率是 %.3f%% ' % ((bounce_user_count/user_count)*100))
按照流失率=只浏览一次界面/总用户计算的话,Bounce Rate 仅是 0.069% 左右,所以平台整体流失率是相当低的。
可以换一种指标的定义,是不是可以把只有浏览记录再无其他行为的用户视为流失用户,分析此类人群的跳失原因。之后可以细分到各个商品种类以及各个商品,计算其用户跳失率并采取相应的措施。
4.1.3 用户转化情况
接下来分析用户从浏览到最后下单的转化情况,首先先了解一下用户浏览、收藏、加购物车和购买行为的整体分布趋势。
behavior_detail=df.groupby(['behavior_type','hour'])['user_id'].count().reset_index().rename(columns={'user_id':'total_behavior'})

pv量十分大,但是用户加购物车、收藏和购买数依次降低,而且体量相比于pv是很小的,接下来通过漏斗模型来看看整体分析用户转化情况。
下面我们用漏斗图来更加直观的看一下:

可以看出,向购物车转化的百分比为6.25%,从购物车向收喜爱转化比率为51.92%,从喜爱向购买转化的比率为68.99%。整体而言由pv向cart转化的时候需要重点关注。
接下来分析一下用户的留存率
先写一个计算n日留存率的函数:
# 计算n日留存率
def cal_retention(n):
# 用于记录出现过的user_id
user_list=[]
# 取最后一天的前N天
cal_date=pd.Series(df['date'].unique()).sort_values()[:-n]
# 用于存储最后留存率结果
retention_rates=[]
for to_date in cal_date:
# 通过与已经有记录的用户列表的集合对比,识别新用户
new_user_list=set(df[df['date']==to_date]['user_id'])-set(user_list)
# 用于存储最后留存率结果
user_list.extend(new_user_list)
# 第n天留存情况
user_ndate=df[df['date']==to_date+timedelta(n)]['user_id'].unique()
retention_cnt=0
for user_id in user_ndate:
if user_id in new_user_list:
retention_cnt+=1
retention_rate=retention_cnt/len(new_user_list)
# 汇总N日留存数据
retention_rates.append(retention_rate)
u_retention=pd.Series(retention_rates,index=cal_date)
return u_retention
整理成dataframe的形式:
pd.DataFrame({'1':cal_retention(1),'2':cal_retention(2),'3':cal_retention(3),'4':cal_retention(4),'5':cal_retention(5),'6':cal_retention(6),'7':cal_retention(7)})

可能是截取数据的原因?1号2号出现了留存率为1的情况,这是不可能的。但是可以看到12月1号的活动是有明显效果的。(今后会研究一下为什么会出现1的情况~)
(二)用户消费习惯分析
4.2.1 用户付费率PUR(Paying User Rate)
#根据用户付费率 = 有购买记录的用户 / 活跃用户计算:
paying_user_count=df[df.behavior_type=='buy'].user_id.unique().shape[0]
paying_user_count
print('用户付费率PUR %.2f%%' % ( 100 * paying_user_count / user_count))
可知用户付费率PUR为 67.95%,嗯~看来用户付费率还是比较高的。
4.2.2 用户购买次数
user_buy_time=df[df.behavior_type=='buy'].groupby('user_id')['behavior_type'].count().reset_index().rename(columns={'behavior_type':'buy_times'})
buy_time_total=user_buy_time.groupby('buy_times')['user_id'].count().reset_index().rename(columns={'user_id':'count'})
buy_time_total.head()


print('购买次数10次及以内的用户占比为 %.2f%%' % (100*(buy_time_total.iloc[0:10,1].sum()/paying_user_count)))
购买次数10次及以内的用户占比为 97.64%
4.2.3 用户复购率
#根据用户复购率 = 多次购买用户数 / 总付费用户计算:
#总付费用户:paying_user_count,现在要从buy_time_total表中筛选出购买次数>2的人数总和
payinguser_over_two=buy_time_total[buy_time_total.buy_times>=2]['count'].sum()
print('用户的复购率为 %.2f%%' % (100*(payinguser_over_two/paying_user_count)))
用户的复购率为 65.77%,下面看看复购时间是怎样的吧~
buyer_retention_diff=df[df.behavior_type=='buy'].groupby('user_id').date.apply(lambda x:x.sort_values().diff().dropna()).reset_index()
buyer_retention_diff=buyer_retention_diff[['user_id','date']]
buyer_retention_diff.describe()

可以看出有75%的客人2天内均有复购表现,50%的人当天有多次购买表现。
4.2.4 商品大类销售分析
#分析商品浏览TopN和商品销售TopN的数据:
top=pd.pivot_table(df,index=['item_id','category_id'],values = 'user_id', columns = 'behavior_type', fill_value=0,
aggfunc='count', margins = True)
top.head()

# 定义计算销售/浏览TopN的函数
def cal_topN(index,behavior_type,n):
topN=pd.pivot_table(df,index=index,values='user_id', columns='behavior_type',fill_value=0,
aggfunc='count').sort_values(by=behavior_type,ascending=False).head(n)
topN['paying_rate']=topN.apply(lambda x:x.buy/x.pv,axis = 1)
topN=topN[['pv','buy','paying_rate']]
return topN
#按照pv排名的前十商品
category_pv_topN=cal_topN('category_id','pv',10)
category_pv_topN.reset_index()

#按照buy排名的前十商品
category_buy_topN = cal_topN('category_id','buy',10)
category_buy_topN.reset_index()

#进一步查看购买量前10和浏览量前10的交集:
category_pv_buy_topN=pd.merge(category_pv_topN,category_buy_topN,on='category_id')
category_pv_buy_topN

对于浏览量高但是购买率比较低的产品,需要特别关注原因所在,先要知道该商品是否是日常属性的商品, 然后针对商品属性做出合理假设,比如说是商品的描述不清楚?还是价格偏高?还是长期断货状态?还是选择了相似的其他产等等
4.2.5 商品大类行为分析
# 筛选出产生购买行为的数据
df_buy=df[df['behavior_type']=='buy']
# 计算各种商品大类的交易数
buy_category=df_buy[['category_id','behavior_type']].groupby('category_id').count() \
.rename(columns={'behavior_type':'buy_count'}).reset_index().sort_values('buy_count',ascending=False)
buy_category.head()
buy_category表如下:

# 将产生购买行为的数据和原数据外连接,进而得到有购买记录的商品大类的其他行为信息
behav_category=pd.merge(df_buy[['user_id','category_id']],df,
on=['user_id','category_id'],how='left')
behav_category.head()

然后来看每个id对应着有多少个操作行为
behav_category_count=behav_category[['category_id','behavior_type']].groupby('category_id').count() \
.reset_index().rename(columns={'behavior_type':'behavior_count'})
behav_category_count.head()

现在商品别购买行为总次数和其他行为总次数都有了,来汇总一下到一张表上:
# 统计分析各种商品大类的购买数和产生行为数
buy_behav_category=pd.merge(buy_category,behav_category_count,on = 'category_id',how = 'inner')
buy_behav_category=buy_behav_category.assign(behav_per_buy=buy_behav_category['behavior_count']/buy_behav_category['buy_count'])
buy_behav_category.head()

用tableau可视化:

由上图可知,大部分购买行为平均只会产生25次以内的行为,可以据此对商品初步分类,以实施不同的运营策略。
购买量大、行为数多(上图右上部分):推测该区域商品是快销产品或高频刚需物品,不仅销量大而且可选择品牌众多,如食品、日用品、护肤品和衣物服装等。平台可以据此将该商品类别建立专区,可以同时浏览查看该类别下的诸多产品,减少用户的多次搜索,提升用户体验度。
购买量大、行为数少(上图左上部分):推测该区域商品主要为高频产品,行为数少说明可能品牌种类少、被少数品牌垄断,或者是用户对某品牌建立了一定的依赖度等等。此类区域的商品,用户决策相对会轻松,因此应着重快速让用户触达商品,可以优先展示用户购买过的品牌等。
购买量小、行为数少(上图左下部分):大多数商品大类都集中分布在这个区域,应该针对具体类别具体分析。比如可以根据业务实际情况锁定范围,看该范围内商品分别归属于哪一类,看看是这一类商品性质的原因还是什么地方出现差错。
购买量小、行为数多(上图右下部分):推测该区域商品低频或者商品贵重,用户需要货比三家、再三考虑后下单,对此可以改善商品的介绍方式,如现在的品牌直播,让用户更快速、直观的了解商品。
(三)用户价值分析
这里利用RFM模型去分析用户价值,以便针对不同用户采取不同措施。RFM模型的概念如下:
- R(Recency):客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则表示客户交易发生的日期越近。
- F(Frequency):客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。
- M(Monetary):客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
由于所给数据集不包含用户购买金额,所以只考虑最近消费时间R和购买频率F,将客户分为R近F高(价值客户),R远F高(保持客户),R远F低(挽留客户),R近F低(发展客户)四类,有价值的客户、保持客户、发展客户和挽留客户。
# 1 R: 最近一次消费距今天数统计
nowDate=datetime.date(2017,12,4) # 假定当前时间为(2017,12,4)
user_recent_pay=df[df['behavior_type']=='buy'].groupby('user_id')['date'] \
.apply(lambda x: nowDate-x.sort_values().iloc[-1])
user_recent_pay=user_recent_pay.reset_index().rename(columns={'date':'recent'})
user_recent_pay.head()
# 2 F:最近一段时间交易的次数统计
user_paying_times=df[df['behavior_type']=='buy'].groupby('user_id')['date'].count().reset_index() \
.rename(columns={'date':'paying_times'})
user_paying_times.head()
# 3 通过user_id将R、F合并
rfm=pd.merge(user_recent_pay,user_paying_times,on='user_id')
合并结果为:

# 4 给R、F打分score
rfm['score_recent']=pd.qcut(rfm['recent'],2,labels=['1', '0'])
rfm['score_freq']=pd.qcut(rfm['paying_times'],2,labels=['0', '1'])
# 5 得分拼接
rfm['rfm'] = rfm['score_recent'].str.cat(rfm['score_freq'])
# 6 根据RFM分类
rfm = rfm.assign(user_type=rfm['rfm'] \
.map({'11':'重要客户', '01':'保持客户', '10':'发展客户', '00':'挽留客户'})) #assign()
rfm.head()
得到RFM表:

最后,将其可视化:

由上图可知重要客户和发展客户比例相当,各占总用户的三分之一左右,挽留客户最少。
五、总结与建议
总结分析的结论并提出一些建议
5.1 用户行为分析
- 12月2日12月3日相较于其他日期用户活跃度、各指标增长明显。与同样是周末的11月25日、11月26日pv环比增长率31.4%,uv环比增长率35.7%,推测是12月2日周五平台开始双十二预热活动或其他活动所致。
- 用户的活跃时间从10:00持续到晚上22:00,其中5:00-10:00和18:00-21:00是用户活跃度迅速增长的时段。21:00点左右达到一天峰值,这符合大多数人的日常作息规律,由此可以建议店铺调整客服工作时间,增加18:00-22:00点的客服数量,提升用户的购买率。仔细观察的话,可以发现10:00和15:00分别达到了一个小高峰,所以可以在这两个时间段开始推广活动等。
5.2 用户消费分析
- 用户付费率达到67.95%。
- 针对付费用户来看,用户平均消费次数为3次,其中购买次数为1次的用户数量最多,购买次数10次及以内的用户占比为97.64%。
- 用户复购率为65.77%,用户复购平均间隔1.16天,可以看出有75%的客人2天内均有复购表现,50%的人当天有多次购买表现。
- 通过比对商品大类浏览top10和商品大类销售top10可知,存在某些商品浏览量高但成交量相对较低,对此应该分析用户流失原因,对症下药;对于成交量高但浏览量相对较低的商品,是否应该考虑增加商品的曝光率等等。
- 观察得知商品大类4159072和1464116商品转换率较高,分别达到了10%和5%以上,应该进一步分析这些商品成交率高的原因,是否能推广到其它商品。
- 在不同日期的不同时间点,商品销量具有不同的表现,可进一步对商品按照时间维度进行挖掘分析,更加精准地投放商品广告。
- 商品发生购买前产生的用户行为多在25次之内,可以将行为量和购买量这两个维度上找其平均值并将区域分为四个部分,针对各个部分可以进一步寻找商品类别上的特性和个别异常商品。
5.3 用户价值分析
此部分将用户分为四个维度,针对不同维度的用户应当采取不同的运营策略:
- 针对重要客户(近期有付费且经常付费),即忠实用户,他们可能不需要额外的刺激消费,可以关注其售后体验等,提升用户的消费满意度;
- 针对保持客户(经常付费但是已经在很久之前了),曾经的忠实用户面临流失的风险,对其可以进行适当的提醒,如消息推送,还可以了解其离开的原因,以采取相应措施。
- 针对发展客户(近期有付费但是次数很少,或者只有一次付费),即新用户或者黏性较低的用户,我们的目标是刺激他们消费,可以通过开展促销活动等措施。
- 针对挽留客户(很少付费而且在很久之前),即流失用户,需要挽回并刺激其消费。从另一方面来看,可以尝试寻找用户流失的原因,通过反馈来调整我们的产品。