项目背景及来源
数据来源:天池大数据https://tianchi.aliyun.com/dataset/dataDetail?dataId=649&userId=1
数据说明:我们随机选择约100万用户,这些用户在2017年11月25日至12月3日之间具有点击,购买,向购物车中添加商品和偏好商品的行为。
数据集列名说明:
type类型说明:
思维导图:
数据读取、分析及可视化
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
数据集数据过大,只选取前1000w行(参考其他人做法)
columns=["userid", 'itemid', 'categoryid', 'type', 'timestamp']
data = pd.read_csv(r'E:\找工作\淘宝用户行为\UserBehavior.csv',
engine='python',
encoding='utf-8',
names=columns,
chunksize=10000000,
iterator=True)
dataframe = data.get_chunk(10000000)
查看数据类型
dataframe.info()
查看数据前五行
dataframe.head()

查看是否有缺失值
dataframe.isnull().sum()
将时间戳数据转换成北京时间
import datetime
dataframe['time']=pd.to_datetime(dataframe['timestamp'],unit='s')+datetime.timedelta(hours=8)
根据项目背景选取时间区间,并拆分日期和时间
startTime = datetime.datetime.strptime("2017-11-25 00:00:00","%Y-%m-%d %H:%M:%S")
endTime = datetime.datetime.strptime("2017-12-03 23:59:59","%Y-%m-%d %H:%M:%S")
dataframe = dataframe[(dataframe.time>=startTime)&(dataframe.time<=endTime)]
dataframe = dataframe.reset_index(drop=True)
dataframe['date'] = dataframe.time.dt.date
dataframe['hour'] = dataframe.time.dt.hour
基本信息
total_unique_users = dataframe.userid.nunique()
total_unique_itemid = dataframe.itemid.nunique()
total_unique_categoryid = dataframe.categoryid.nunique()
user_bought_count = dataframe[dataframe['type']=='buy'].userid.nunique()
user_nobought_count=dataframe[dataframe['type']!='buy'].userid.nunique()
user_nobought_count = total_unique_users - user_bought_count
print(f"UV:{total_unique_users}")
print(f"商品总数:{total_unique_itemid}")
print(f"分类数:{total_unique_categoryid}")
print(f"付费用户数:{user_bought_count}")
print(f"非付费用户数:{user_nobought_count}")
print(f"付费用户占比:{user_bought_count/total_unique_users*100:.2f}%")
各行为类型的总量
type_series = dataframe['type'].value_counts()
type_series
各行为占比(饼图)
plt.figure(figsize=(8,8))
patches,l_text,p_text=plt.pie(x=type_series,labels=type_series.index,autopct='%1.2f%%')
for t in p_text:
t.set_size(20)
for t in l_text:
t.set_size(40)
plt.title('顾客各行为占比',size=20)
plt.show()
点击量是最多的,占89.49%,加购5.59%,收藏2.92%,购买1.99%
进一步数据分析查看,平均每天的各行为的总量,已经平均每个用户的各行为的总量,以及平均每个曾购买过的用户的各类行为的总量。
type_df=pd.DataFrame([type_series,type_series/9,type_series/total_unique_users],
index=['total','avg_day','avg_user'])
type_df.loc['paying_user']=dataframe[dataframe['userid'].isin(dataframe[dataframe['type']=='buy']['userid'])].type.value_counts()
type_df
可以看到最后一行数据急剧增大,可以看出购买过的用户的淘宝动作照比没有购买过的用户频繁的多。
groupby_userid = dataframe.groupby(by='userid')
user_type = groupby_userid.type.value_counts().unstack() # 使用unstack进行不堆叠操作,列方向上的索引转成行方向的索引
only_pv_users = user_type[user_type['pv']==user_type.sum(axis=1)]
bounce_rate = only_pv_users.shape[0]/total_unique_users
print("只浏览网页的占比:{:.2f}%".format(bounce_rate*100))
只浏览网页的占比:5.74%
repurchase_users = user_type[user_type['buy']>=2].shape[0]
repurchase_rate = repurchase_users/user_bought_count
print("复购率:{:.2f}%".format(repurchase_rate*100)
复购率:66.01%
user_type[user_type['buy']>=2]['buy'].plot(kind='hist',bins=20)
用户转化漏斗分析
pv_df = dataframe[dataframe['type']=='pv']
buy_df = dataframe[dataframe['type']=='buy']
cart_df = dataframe[dataframe['type']=='cart']
fav_df = dataframe[dataframe['type']=='fav']
# process1 点击->加购->购买
pv_cart_df = pd.merge(left=pv_df,right=cart_df,how='inner',on=['userid','itemid','categoryid'],suffixes=('_pv','_cart'))
cart_buy_df = pd.merge(left=cart_df,right=buy_df,how='inner',on=['userid','itemid','categoryid'],suffixes=('_cart','_buy'))
count_users_pv_cart = pv_cart_df[pv_cart_df.time_pv < pv_cart_df.time_cart].userid.nunique()
count_users_cart_buy = cart_buy_df[cart_buy_df.time_cart < cart_buy_df.time_buy].userid.nunique()
# process2 点击->收藏->购买
pv_fav_df = pd.merge(left=pv_df,right=fav_df,how='inner',on=['userid','itemid','categoryid'],suffixes=('_pv','_fav'))
fav_buy_df = pd.merge(left=fav_df,right=buy_df,how='inner',on=['userid','itemid','categoryid'],suffixes=('_fav','_buy'))
count_user_pv_fav = pv_fav_df[pv_fav_df.time_pv < pv_fav_df.time_fav].userid.nunique()
count_user_fav_buy = fav_buy_df[fav_buy_df.time_fav < fav_buy_df.time_buy].userid.nunique()
fav_cart_ratio = (count_user_pv_fav+count_users_pv_cart)/total_unique_users
buy_ratio=(count_user_fav_buy+count_users_cart_buy)/total_unique_users
print('收藏加购用户转化率为:%.2f%%'%(fav_cart_ratio*100))
print('购买用户转化率为:%.2f%%'%(buy_ratio*100))
时间维度
查看11-25至12-03期间每天各行为的数量
df=dataframe.groupby(['date','type']).count().reset_index()
df=df.loc[:,['date','type','userid']]
df.rename(columns={'userid':'sum'}, inplace=True)
df['week'] = pd.to_datetime(df['date'],format='%Y-%m-%d ').dt.weekday+1
df
可视化
for i in df['type'].unique():
date_type=list(df[df['type']==i]['date'])
sum_type=list(df[df['type']==i]['sum'])
plt.plot(date_type,sum_type,label=i)
plt.legend()
plt.xlabel('日期')
plt.ylabel('总数')
plt.show()
查看基于时段的行为分布图
bins=[0,6,12,18,24]
df1=dataframe.copy()
df1['hour']=pd.cut(df1['hour'],bins)
sns.countplot('hour',data=df1,hue='type')
plt.show()
可以看出夜晚的淘宝行为更多一些
每日的独立访客量
df2=dataframe.copy()
uv=df2.groupby(['date'])['userid'].nunique()
plt.figure(figsize=(10,10))
uv.plot()
假设一个用户存在3次及以上行为,则被定义为活跃用户
df2_1=df2.groupby(['date','userid'])['type'].count().reset_index()
df2_active=df2_1[df2_1['type']>=3]
df3=df2_active.groupby(['date'])['userid'].count().reset_index()
df4=pd.merge(uv,df3, how='inner', on=['date','date'])
df4['ratio']=df4['userid_y']/df4['userid_x']
df4
表中的ratio列为每天活跃用户的占比,可以看出活跃用户的登录比处于一个比较稳定的状态,且占比较高,接近80%
buy_df = dataframe[dataframe['type']=='buy']
buy_df_1=buy_df.groupby(['date'])['userid'].nunique().reset_index()
buy_df_2=pd.merge(uv,buy_df_1, how='inner', on=['date','date'])
buy_df_2['ratio']=buy_df_2['userid_y']/buy_df_2['userid_x']
buy_df_2
表中的ratio列为每天曾做出购买动作的用户每天的淘宝占比,显示也是比较的稳定的状态,接近20%。
buy_df_4=pd.merge(uv,buy_df_3, how='inner', on=['date','date'])
buy_df_4['ratio']=buy_df_4['userid_y']/buy_df_4['userid_x']
buy_df_4
图中的ratio列为人均购买量,在0.3件/人左右。
buy_df_5=pd.merge(buy_df_1,buy_df_3, how='inner', on=['date','date'])
buy_df_5['ratio_pay']=buy_df_5['userid_y']/buy_df_5['userid_x']
buy_df_5
图中的ratio_pay为曾购买的用户的人均购买量,基本在1.50件/人左右。
查看活跃用户活跃天数的分布
tmp = dataframe[['userid','date','type']].groupby(by=['userid','date']).count()
user_active_days_df = tmp[tmp['type']>=3].count(level=0)
sorted_user_active_days_df = user_active_days_df['type'].value_counts().sort_index()
sorted_user_active_days_df.plot(kind='bar')
rfm模型
由于数据中没有给出购买金额,可以做出r(最近一次购买时间间隔)和f(一段时间内交易的次数)
last_time_buy=dataframe[dataframe['type']=='buy'].groupby(['userid'])['date'].max().reset_index()
last_time_buy['day']=(pd.to_datetime('2017-12-04')-pd.to_datetime(last_time_buy['date'],format='%Y-%m-%d ')).dt.days
last_time_buy['day']=last_time_buy['day'].astype(int)
last_time_buy['day'].describe()
buy_times=dataframe[dataframe['type']=='buy'].groupby(['userid'])['type'].count().reset_index()
buy_times['type'].describe()
rf=pd.merge(last_time_buy,buy_times, how='inner', on=['userid','userid'])
rf.rename(columns={'day':'r','type':'f'},inplace=True)
rf
建立评分标准:之前查看r在1-9之间,r值越大说明间隔时间越长。所以设定r=1时,评分为4,r=2,3时,评分为3,r=4,5,6时,评分为2,r=7,8,9时,评分为1
f在1-93之间,f值越高,说明购买次数越多,f=1时,评分为1 f=2时,评分为2,f=3时评分为3,f>=4时,评分为4.
当评分皆为4时,则该客户为重要价值客户,如果评分皆为1,为重要挽留客户,如果r评分高于f评分,则是重要挽留客户,其余的未重要保持客户
def R_score(x):
if 0 <= x <= 1:
return 4
elif 2 <= x <= 3:
return 3
elif 4 <= x <= 6:
return 2
elif 7 <= x <= 9:
return 1
else:
return 0
def F_score(x):
if x == 1:
return 1
elif x == 2:
return 2
elif x == 3:
return 3
elif x >= 4:
return 4
else:
return 0
rf['R_score'] = rf.r.map(R_score)
rf['F_score'] = rf.f.map(F_score)
for i in range(len(rf)):
if rf.loc[i,'R_score']>=4 and rf.loc[i,'F_score']>=4:
rf.loc[i,'客户属性']='重要价值客户'
elif rf.loc[i,'R_score']<=1 and rf.loc[i,'F_score']<=1:
rf.loc[i,'客户属性']='重要挽留客户'
elif rf.loc[i,'R_score']>rf.loc[i,'F_score']:
rf.loc[i,'客户属性']='重要挽留客户'
else:
rf.loc[i,'客户属性']='重要保持客户'
rf
rf['客户属性'].value_counts()
rf['客户属性'].value_counts(1)
基于商品销售分析
查看购买量前十的商品,并显示购买/浏览的比率
item=dataframe.groupby(['itemid'])['type'].value_counts().unstack()
item.replace(to_replace=np.nan, value=0, inplace=True) # 缺失值补0
item = item.sort_values(by='buy', ascending=False) # 按购买量降序排列
item['buy_pv_conversion_rate']=item['buy']/item['pv']
item.head(10)
可以看到3122135这个商品销量最好,购买的次数占浏览的次数接近70%,也是销量前十的转化率最高的产品。
品类根据销量排名前十名和对应的浏览-购买转化率
category_type_df= dataframe.groupby(by='categoryid')['type'].value_counts().unstack()
category_type_df.replace(to_replace=np.nan, value=0, inplace=True)
category_type_df = category_type_df.sort_values(by='buy', ascending=False)
category_type_df['buy_pv_conversion_rate'] = category_type_df['buy']/category_type_df['pv']
category_type_df.head(10)
销量前十名的品类对应的转化率很低。
品类浏览-购买转化率的分布图
sns.distplot(category_type_df[(category_type_df['buy_pv_conversion_rate']<=1)&(category_type_df['buy_pv_conversion_rate']>0)]['buy_pv_conversion_rate'],
kde=False)
plt.show()
品类的转化率较低,大部分的品类分布在0.2以下
以上思考:
1.淘宝用户的复购率较高,但次数较少,可考虑产品质量、性价比以及售后服务方面入手解决问题。
2.周末的各项指标都优于周内,周六周日用户尤为活跃,用户有更多的时间可以逛淘宝,因此一些营销活动应当在周六周日进行。基于日期可以发现2017/12/02当天上升明显,尤其,2017/12/02和17/11/25同为周六,相比之下,2017/12/2点击量上升尤为明显,这是因为2017/12/02当天淘宝开始为“双十二”活动因此吸引了更多的点击量。不能作为日常淘宝用户行为的分析。
3.晚上时段逛淘宝的用户最多,一些活动可以选择在晚上进行力度更强
4.根据RFM模型对用户分类后发现重要发展客户比例最高,其次是保持用户,提高社群管理的效率,将重要保持客户和重要发展客户转变为重要价值客户,可采取定期发送文案、赠送优惠券等方式。
5.根据销量高的产品排名并同时分析点击量和购买量了解商品市场情况。不断优化用户体验和商品展示(或商品选品),提高购买转化率。