项目背景
本数据报告以某电商用户行为数据为数据集,通过行业的指标对淘宝用户行为进行分析,从而探索某电商用户的行为模式,具体指标包括:日PV和日UV分析,付费率分析,漏斗流失分析和用户价值RFM分析。
理解数据
本数据集为某电商2014年11月18日至2014年12月18日的用户行为数据,共计6列字段,列字段分别是:
user_id:用户身份,脱敏
item_id:商品ID,脱敏
behavior_type:用户行为类型(包含点击、收藏、加购物车、支付四种行为,分别用数字1、2、3、4表示)
user_geohash:地理位置
item_category:品类ID(商品所属的品类)
time:用户行为发生的时间
数据清洗
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 去除警告日志提醒的显示
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
#解决中文乱码等显示问题
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
%config InlineBackend.figure_format = 'svg'
data = pd.read_csv(r"D:\学习\数据分析项目\淘宝用户行为分析\tianchi_mobile_recommend_train_user\tianchi_mobile_recommend_train_user.csv")
data.head()
user_id | item_id | behavior_type | user_geohash | item_category | time | |
---|---|---|---|---|---|---|
0 | 98047837 | 232431562 | 1 | NaN | 4245 | 2014-12-06 02 |
1 | 97726136 | 383583590 | 1 | NaN | 5894 | 2014-12-09 20 |
2 | 98607707 | 64749712 | 1 | NaN | 2883 | 2014-12-18 11 |
3 | 98662432 | 320593836 | 1 | 96nn52n | 6562 | 2014-12-06 10 |
4 | 98145908 | 290208520 | 1 | NaN | 13926 | 2014-12-16 21 |
缺失值处理
data.isnull().sum()
user_id 0
item_id 0
behavior_type 0
user_geohash 8334824
item_category 0
time 0
dtype: int64
data.fillna('miss',inplace=True)
标准化处理
#拆分数据集
import re
data['date'] = data['time'].map(lambda s: re.compile(' ').split(s)[0])
data['hour'] = data['time'].map(lambda s: re.compile(' ').split(s)[1])
data.head()
user_id | item_id | behavior_type | user_geohash | item_category | time | date | hour | |
---|---|---|---|---|---|---|---|---|
0 | 98047837 | 232431562 | 1 | miss | 4245 | 2014-12-06 02 | 2014-12-06 | 02 |
1 | 97726136 | 383583590 | 1 | miss | 5894 | 2014-12-09 20 | 2014-12-09 | 20 |
2 | 98607707 | 64749712 | 1 | miss | 2883 | 2014-12-18 11 | 2014-12-18 | 11 |
3 | 98662432 | 320593836 | 1 | 96nn52n | 6562 | 2014-12-06 10 | 2014-12-06 | 10 |
4 | 98145908 | 290208520 | 1 | miss | 13926 | 2014-12-16 21 | 2014-12-16 | 21 |
data.dtypes
user_id int64
item_id int64
behavior_type int64
user_geohash object
item_category int64
time object
date object
hour object
dtype: object
#将time列和date列转化为日期类数据类型,hour列应该是字符串数据类型。
#数据类型转化
data['date']=pd.to_datetime(data['date'])
data['time']=pd.to_datetime(data['time'])
data['hour']=data['hour'].astype('int64')
data.dtypes
user_id int64
item_id int64
behavior_type int64
user_geohash object
item_category int64
time datetime64[ns]
date datetime64[ns]
hour int64
dtype: object
data = data.sort_values(by='time',ascending=True)#排序处理
data = data.reset_index(drop=True)#建立索引
data
user_id | item_id | behavior_type | user_geohash | item_category | time | date | hour | |
---|---|---|---|---|---|---|---|---|
0 | 73462715 | 378485233 | 1 | miss | 9130 | 2014-11-18 00:00:00 | 2014-11-18 | 0 |
1 | 36090137 | 236748115 | 1 | miss | 10523 | 2014-11-18 00:00:00 | 2014-11-18 | 0 |
2 | 40459733 | 155218177 | 1 | miss | 8561 | 2014-11-18 00:00:00 | 2014-11-18 | 0 |
3 | 814199 | 149808524 | 1 | miss | 9053 | 2014-11-18 00:00:00 | 2014-11-18 | 0 |
4 | 113309982 | 5730861 | 1 | miss | 3783 | 2014-11-18 00:00:00 | 2014-11-18 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
12256901 | 132653097 | 119946062 | 2 | miss | 6054 | 2014-12-18 23:00:00 | 2014-12-18 | 23 |
12256902 | 130082553 | 296196819 | 1 | miss | 11532 | 2014-12-18 23:00:00 | 2014-12-18 | 23 |
12256903 | 43592945 | 350594832 | 1 | 9rhhgph | 9541 | 2014-12-18 23:00:00 | 2014-12-18 | 23 |
12256904 | 12833799 | 186993938 | 1 | 954g37v | 3798 | 2014-12-18 23:00:00 | 2014-12-18 | 23 |
12256905 | 77522552 | 69292191 | 1 | miss | 889 | 2014-12-18 23:00:00 | 2014-12-18 | 23 |
12256906 rows × 8 columns
用户行为分析
PV(访问量):即Page View, 具体是指网站的是页面浏览量或者点击量,页面被刷新一次就计算一次。
UV(独立访客):即Unique Visitor,访问网站的一台电脑客户端为一个访客。
日访问量分析
#pv_daily记录每天用户操作次数,uv_daily记录每天不同的上线用户数量
pv_daily = data.groupby('date')['user_id'].count().reset_index().rename(columns={'user_id':'pv'})
uv_daily = data.groupby('date')['user_id'].apply(lambda x:x.drop_duplicates().count()).reset_index().rename(columns={'user_id':'uv'})
fig,axes=plt.subplots(2,1)
pv_daily.plot(x='date',y='pv',ax=axes[0])
uv_daily.plot(x='date',y='uv',ax=axes[1])
axes[0].set_title('pv_daily')
axes[1].set_title('uv_daily')
plt.show()
结果显示如上图所示,在双十二期间,pv和uv访问量达到峰值,并且可以发现,uv和pv两个访问量数值差距比较大。
小时访问量分析
#pv_hour记录每小时用户操作次数,uv_hour记录每小时不同的上线用户数量
pv_hour = data.groupby('hour')['user_id'].count().reset_index().rename(columns={'user_id':'pv'})
uv_hour = data.groupby('hour')['user_id'].apply(lambda x:x.drop_duplicates().count()).reset_index().rename(columns={'user_id':'uv'})
fig,axes = plt.subplots(2,1,sharex=True)
pv_hour.plot(x='hour',y='pv',ax=axes[0])
uv_hour.plot(x='hour',y='uv',ax=axes[1])
axes[0].set_title('pv_hour')
axes[1].set_title('uv_hour')
plt.show()
pv和uv在凌晨0-5点期间波动情况相同,都呈下降趋势,访问量在5点时达到最低点,同时在晚上18:00左右,pv波动情况比较剧烈,相比来看uv不太明显,可以看出晚上18:00以后是淘宝用户访问app的活跃时间段。
不同行为类型用户pv分析
pv_detail = data.groupby(['behavior_type','hour'])['user_id'].count().reset_index().rename(columns={'user_id':'total_pv'})
fig,axes = plt.subplots(2,1,sharex=True)
sns.pointplot(x='hour',y='total_pv',hue='behavior_type',data=pv_detail,ax=axes[0])
sns.pointplot(x='hour',y='total_pv',hue='behavior_type',data=pv_detail[pv_detail.behavior_type!=1],ax=axes[1])
axes[0].set_title('pv_different_behavior_type')
plt.show()
图表显示:点击这一用户行为相比较于其他三类用户行为,pv访问量较高,同时四种用户行为的波动情况基本一致,因此晚上这一时间段不管哪一种用户行为,pv访问量都是最高的。
用户消费行为分析
用户购买次数情况分析
data_buy=data[data.behavior_type==4].groupby('user_id')['behavior_type'].count()
sns.displot(data_buy)
plt.title('daily_buy')
plt.show()
data_buy=data[data.behavior_type==4].groupby('user_id')['behavior_type'].count().reset_index().rename(columns={'behavior_type':'buy_count'})
data_buy.describe()
user_id | buy_count | |
---|---|---|
count | 8.886000e+03 | 8886.000000 |
mean | 7.152087e+07 | 13.527459 |
std | 4.120719e+07 | 19.698786 |
min | 4.913000e+03 | 1.000000 |
25% | 3.567731e+07 | 4.000000 |
50% | 7.238800e+07 | 8.000000 |
75% | 1.071945e+08 | 17.000000 |
max | 1.424559e+08 | 809.000000 |
bins = [1,10,20,50]
data_buy['buy_count_cut'] = pd.cut(data_buy['buy_count'],bins,labels = ['1-10','10-20','20-50'])
buy_count_cut = data_buy['buy_count_cut'].value_counts()
buy_count_cut
1-10 4472
10-20 1972
20-50 1417
Name: buy_count_cut, dtype: int64
淘宝用户消费次数普遍在10次以内,因此需要重点关注购买次数在10次以上的消费者用户群体。
付费率
付费率=消费人数/活跃用户人数
data.groupby('date').apply(lambda x:x[x.behavior_type==4].count()/len(x.user_id.unique())).plot()
plt.title('付费率')
Text(0.5, 1.0, '付费率')
每天活跃用户人群中,大概6%的用户具有消费行为,在双十二期间消费用户人数最多。
漏斗流失分析
浏览主页——点击商品——加入购物车&收藏——开始支付——完成购买
data_user = data.groupby(['behavior_type']).count()
data_user.head()
user_id | item_id | user_geohash | item_category | time | date | hour | |
---|---|---|---|---|---|---|---|
behavior_type | |||||||
1 | 11550581 | 11550581 | 11550581 | 11550581 | 11550581 | 11550581 | 11550581 |
2 | 242556 | 242556 | 242556 | 242556 | 242556 | 242556 | 242556 |
3 | 343564 | 343564 | 343564 | 343564 | 343564 | 343564 | 343564 |
4 | 120205 | 120205 | 120205 | 120205 | 120205 | 120205 | 120205 |
pv_all=data['user_id'].count()
print(pv_all)
12256906
总浏览量:12256906
点击量:11550581
收藏量+加购量:242556+343564= 586120
购买量:120205
点击量-购买意向 流失率:94.93%
购买意向-购买量 流失率:79.49%
在本数据集中,缺少“下单”的用户行为数据,所以无法分析出用户下单到最终付款完后完成的流失率。
同时,因为收藏与加购两个用户行为并不存在上下级关系,所以合并为购买意向进行分析。
用户价值度RFM模型分析
RFM的含义:
R(Recency):客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则表示客户交易发生的日期越近。
F(Frequency):客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。
M(Monetary):客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
from datetime import datetime
datenow=datetime(2014,12,20)
#每位用户最近购买时间
recent_buy_time=data[data.behavior_type==4].groupby('user_id').date.apply(lambda x:datetime(2014,12,20)-x.sort_values().iloc[-1]).reset_index().rename(columns={'date':'recent'})
#每个用户消费频率
buy_freq=data[data.behavior_type==4].groupby('user_id').date.count().reset_index().rename(columns={'date':'freq'})
rfm=pd.merge(recent_buy_time,buy_freq,left_on='user_id',right_on='user_id',how='outer')
#对各维度进行打分
rfm['recent_value']=pd.qcut(rfm.recent,2,labels=['2','1'])
rfm['freq_value']=pd.qcut(rfm.freq,2,labels=['1','2'])
rfm['rfm']=rfm['recent_value'].str.cat(rfm['freq_value'])
rfm.head()
user_id | recent | freq | recent_value | freq_value | rfm | |
---|---|---|---|---|---|---|
0 | 4913 | 4 days | 6 | 2 | 1 | 21 |
1 | 6118 | 3 days | 1 | 2 | 1 | 21 |
2 | 7528 | 7 days | 6 | 1 | 1 | 11 |
3 | 7591 | 7 days | 21 | 1 | 2 | 12 |
4 | 12645 | 6 days | 8 | 2 | 1 | 21 |
from datetime import datetime
datenow=datetime(2014,12,20)
#每位用户最近购买时间
recent_buy_time=data[data.behavior_type==4].groupby('user_id').date.apply(lambda x:datetime(2014,12,20)-x.sort_values().iloc[-1]).reset_index().rename(columns={'date':'recent'})
#每个用户消费频率
buy_freq=data[data.behavior_type==4].groupby('user_id').date.count().reset_index().rename(columns={'date':'freq'})
rfm=pd.merge(recent_buy_time,buy_freq,left_on='user_id',right_on='user_id',how='outer')
#对各维度进行打分
rfm['recent_value']=pd.qcut(rfm.recent,2,labels=['2','1'])
rfm['freq_value']=pd.qcut(rfm.freq,2,labels=['1','2'])
rfm['rfm']=rfm['recent_value'].str.cat(rfm['freq_value'])
rfm.head()
user_id | recent | freq | recent_value | freq_value | rfm | |
---|---|---|---|---|---|---|
0 | 4913 | 4 days | 6 | 2 | 1 | 21 |
1 | 6118 | 3 days | 1 | 2 | 1 | 21 |
2 | 7528 | 7 days | 6 | 1 | 1 | 11 |
3 | 7591 | 7 days | 21 | 1 | 2 | 12 |
4 | 12645 | 6 days | 8 | 2 | 1 | 21 |
因为本数据集没有提供消费金额,因此只能R和F进行用户价值分析。
通过RF用户价值分析,对于22用户,为重点用户需要关注;对于21这类忠诚度高而购买频率不足的,可以通过活动优惠券等方式提高用户的购买频率;对于12这类忠诚度不高而消费频率低的用户,需要关注他们的购物习性,多做推送,做精准化营销。
rfm.groupby(['rfm']).count()
user_id | recent | freq | recent_value | freq_value | |
---|---|---|---|---|---|
rfm | |||||
11 | 2767 | 2767 | 2767 | 2767 | 2767 |
12 | 1219 | 1219 | 1219 | 1219 | 1219 |
21 | 1721 | 1721 | 1721 | 1721 | 1721 |
22 | 3179 | 3179 | 3179 | 3179 | 3179 |
rfm_count = rfm['rfm'].value_counts()
plt.figure(figsize=(8,8))
plt.pie(rfm_count.values,labels=rfm_count.index,autopct='%.2f%%',
wedgeprops={'linewidth':0.5,'edgecolor':'green'},
textprops={'fontsize':30,'color':'#003371'}
)
plt.title('RFM',size=30)
plt.show()