淘宝用户行为分析

项目背景及来源

数据来源:天池大数据https://tianchi.aliyun.com/dataset/dataDetail?dataId=649&userId=1
数据说明:我们随机选择约100万用户,这些用户在2017年11月25日至12月3日之间具有点击,购买,向购物车中添加商品和偏好商品的行为。
数据集列名说明:

image.png

type类型说明:
image.png

思维导图:

image.png

数据读取、分析及可视化

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()
image.png

查看数据前五行

dataframe.head()

![image.png](https://upload-images.jianshu.io/upload_images/24895269-54e03e9011593507.png?
imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
查看是否有缺失值

dataframe.isnull().sum()
image.png

将时间戳数据转换成北京时间

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}%")           
image.png

各行为类型的总量

type_series = dataframe['type'].value_counts()
type_series
image.png

各行为占比(饼图)

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()
image.png

点击量是最多的,占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
image.png

可以看到最后一行数据急剧增大,可以看出购买过的用户的淘宝动作照比没有购买过的用户频繁的多。

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)
image.png
用户转化漏斗分析
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
image.png

可视化

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()
image.png

查看基于时段的行为分布图

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()
image.png

可以看出夜晚的淘宝行为更多一些
每日的独立访客量

df2=dataframe.copy()
uv=df2.groupby(['date'])['userid'].nunique()
plt.figure(figsize=(10,10))
uv.plot()
image.png

假设一个用户存在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
image.png

表中的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
image.png

表中的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
image.png

图中的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
image.png

图中的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')
image.png
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()
image.png
buy_times=dataframe[dataframe['type']=='buy'].groupby(['userid'])['type'].count().reset_index()
buy_times['type'].describe()
image.png
rf=pd.merge(last_time_buy,buy_times, how='inner', on=['userid','userid'])
rf.rename(columns={'day':'r','type':'f'},inplace=True)
rf
image.png

建立评分标准:之前查看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
image.png
rf['客户属性'].value_counts()
rf['客户属性'].value_counts(1)
image.png

image.png
基于商品销售分析

查看购买量前十的商品,并显示购买/浏览的比率

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)
image.png

可以看到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)
image.png

销量前十名的品类对应的转化率很低。

品类浏览-购买转化率的分布图

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()
image.png

品类的转化率较低,大部分的品类分布在0.2以下

以上思考:

1.淘宝用户的复购率较高,但次数较少,可考虑产品质量、性价比以及售后服务方面入手解决问题。
2.周末的各项指标都优于周内,周六周日用户尤为活跃,用户有更多的时间可以逛淘宝,因此一些营销活动应当在周六周日进行。基于日期可以发现2017/12/02当天上升明显,尤其,2017/12/02和17/11/25同为周六,相比之下,2017/12/2点击量上升尤为明显,这是因为2017/12/02当天淘宝开始为“双十二”活动因此吸引了更多的点击量。不能作为日常淘宝用户行为的分析。
3.晚上时段逛淘宝的用户最多,一些活动可以选择在晚上进行力度更强
4.根据RFM模型对用户分类后发现重要发展客户比例最高,其次是保持用户,提高社群管理的效率,将重要保持客户和重要发展客户转变为重要价值客户,可采取定期发送文案、赠送优惠券等方式。
5.根据销量高的产品排名并同时分析点击量和购买量了解商品市场情况。不断优化用户体验和商品展示(或商品选品),提高购买转化率。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355