100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 数据分析3_淘宝用户行为分析_阿里云天池

数据分析3_淘宝用户行为分析_阿里云天池

时间:2020-08-29 01:14:46

相关推荐

数据分析3_淘宝用户行为分析_阿里云天池

淘宝用户行为分析

数据来源

数据链接,我下载的是上传的905.80MB的UserBehavior.csv.zip。

本项目完整源码,提取码9a5v。

为减少篇幅,所以本篇的绘图部分代码没有附上,需要的小伙伴可以点开链接下载完整代码。

项目背景

UserBehavior是阿里巴巴提供的一个淘宝用户行为数据集,用于隐式反馈推荐问题的研究。

本数据集包含了11月25日至12月3日之间,有行为的约一百万随机用户的所有行为(行为包括点击、购买、加购、喜欢)。数据集的组织形式和MovieLens-20M类似,即数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID、行为类型和时间戳组成,并以逗号分隔。

分析目标

用户活跃时段,指标趋势用户对哪些产品、类目感兴趣,付费用户和非付费用户区别转化率,跳失率、复购率用户购买行为特点根据RFM模型对用户分类

数据概览

数据准备

导包

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom pyecharts import charts as pycfrom pyecharts import options as optsimport warnings%matplotlib inline# 忽略警告warnings.filterwarnings("ignore")# 修改matplotlib尺寸plt.rcParams['figure.figsize'] = (20, 8)# 解决matplotlib中文乱码plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']plt.rcParams['axes.unicode_minus'] = False

数据导入

原数据集有1亿多条,内存不够所以无法全部导入,故此次导入1000万条数据进行分析。

# 数据量过大,这里只选取前1000w行# 根据官网介绍给定列名columns = ["userid", 'itemid', 'categoryid', 'type', 'timestamp']# 使用iterator将数据分块,返回迭代器data = pd.read_csv("./UserBehavior.csv", iterator=True,chunksize=10000000, names=columns, parse_dates=['timestamp'])# 将前1000w行数据存放在df df=data.get_chunk(10000000)

查看一下数据信息,共1000万行,前三个字段都是int,后两个是object,我们需要将时间戳转换为日期格式。

数据清洗

将时间戳转为日期。数据集说明中写的是本数据集的日期范围是11月25日至12月3日,所以剔除这日期以外的数据。

import timedef get_unixtime(timeStamp):formatStr = "%Y-%m-%d %H:%M:%S"tmObject = time.strptime(timeStamp, formatStr)return int(time.mktime(tmObject))startTime = get_unixtime("-11-25 00:00:00")endTime = get_unixtime("-12-03 00:00:00")# 保留11月25日至12月3日之间的数据(先减少数据量,再转换可以节省点时间)df = df[(df.timestamp >= startTime) & (df.timestamp <= endTime)]# 要注意时区问题,pd.to_datetime转换的默认时区不是中国df['datetime'] = pd.to_datetime(df.timestamp, unit='s', utc=True).dt.tz_convert("Asia/Shanghai")# 删除时间戳节约内存df.drop('timestamp', inplace=True, axis=1)# 将datetime进行拆分成date和hourdf['date'] = df.datetime.dt.datedf['hour'] = df.datetime.dt.hour

保留下来9994427条数据,最早的是-11-25 00:00:01,最晚的是-12-03 23:59:59。

数据分析

用户流量类指标

# 取消科学计数法,保留两位小数pd.set_option("float_format", lambda x: "%.2f" % x)# 9天总用户量,有操作记录的商品及类目count_users = df.userid.nunique()count_itemid = df.itemid.nunique()count_categoryid = df.categoryid.nunique()count_user_bought=df[df['type']=='buy'].userid.nunique()count_user_nobought = count_users-count_user_bought# 9天总操作记录数types = ["pv", "cart", "fav", "buy"]type_s = df.type.value_counts()# 拼接9天所有、日均、人均指标type_df = pd.DataFrame([type_s, type_s/9, type_s / count_users],columns=types, index=["all", "aver_day", "aver_user"])# 购买过的用户总共浏览了几次,购买了几次type_df.loc['user_bought']=df[df['userid'].isin(df[df['type']=='buy']['userid'].unique())].type.value_counts()# 没有购买过的用户总共浏览了几次购买了几次type_df.loc['user_nobought']=type_df.loc['all']-type_df.loc['user_bought']

print(f"uv:{count_users}")print(f"付费用户数:{count_user_bought}")print(f"付费用户占比:{count_user_bought/count_users*100:.2f}%")print(f"商品数:{count_itemid}")print(f"类目数:{count_categoryid}")# 非付费用户是否比付费用户贡献了更多的PV?print(f"付费用户人均贡献PV:{type_df.loc['user_bought'].pv/count_user_bought:.2f}")print(f"非付费用户人均贡献PV:{type_df.loc['user_nobought'].pv/count_user_nobought:.2f}")print(f"付费用户相较于非付费用户人均多贡献了{((type_df.loc['user_bought'].pv/count_user_bought)/(type_df.loc['user_nobought'].pv/count_user_nobought)-1)*100:.2f}%的PV")

-11-25至-12-03这9天内浏览量总计8944500次,添加购物车总计559127次,收藏产品总计291657次,购买总计199143次。平均每日浏览量993833次,添加购物车62125次,收藏产品32406次,购买22127次。平均每人浏览91次,添加购物车6次,收藏产品3次,购买2次。付费用户占总用户数的67.94%,付费用户相较于非付费用户人均多贡献了35.84%的PV,也就是说付费用户在淘宝app上的使用时间高于非付费用户,应该建立深度的用户画像,进行更精准的商品推荐。

跳失率/复购率

跳失率=只有点击行为的用户/总用户数

其实真正的跳失率应该是只浏览一个页面就离开的访问次数 / 该页面的全部访问次数,这边只是为了突出这些有待发展的客户。

复购率=购买2次及以上用户数/总购买用户数

复购率可以分为按客户计算和按交易计算,这里我采用的是按客户计算。

一定要确定统计周期,像这个数据的统计周期就是9天。

# 将数据按照userid进行分组groupby_userid = df.groupby(by=df.userid)# unstack()可以展开再成为一个dataframeuser_type = groupby_userid.type.value_counts().unstack()# 跳失率# user_type.sum(axis=1)对DataFrame进行横向相加,如果一个userid的pv值==横向相加的和,那就表明他只有点击行为,没有购买/加入购物车/收藏的行为only_pv_users = user_type[user_type['pv'] == user_type.sum(axis=1)]# shape返回的是元组(行数,列数),所以用[0]取出行数bounce_rate = only_pv_users.shape[0]/count_users# 复购率user_bought_twice = user_type[user_type['buy'] >= 2].shape[0]user_bought = user_type[user_type['buy'] >= 1].shape[0]repurchase_rate = user_bought_twice/user_boughtprint("跳失率:{:.2f}%".format(bounce_rate*100))print("复购率:{:.2f}%".format(repurchase_rate*100))print(f"总用户数:{count_users}")

跳失率为5.74%(只浏览不做其他操作的用户比例),这个数值处在可以接受的范围。复购率66.01%,这个数值高是好事情,但是得考虑是不是新客数量越来越少,或者单一渠道获取的顾客已经饱和,是否可以增加别的获客途径。

转化率

因为收藏和加入购物车没有必然关系,所以我们可以将用户的行为路径划分为两种来进行分析:

process1:浏览->收藏->购买process2:浏览->加入购物车->购买

因为每种type都有两种可能性,共有4种type,所以其实总共有16条路径。

# 分别将fav和buy的df提取出来pv_df = df[df['type'] == 'pv']fav_df = df[df['type'] == 'fav']buy_df = df[df['type'] == 'buy']cart_df = df[df['type'] == 'cart']# 将fav_df和buy_df合并,得到收藏后购买的用户人数# process1 浏览->收藏->购买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 = len(pv_fav_df[pv_fav_df.datetime_pv < pv_fav_df.datetime_fav].userid.value_counts())count_user_fav_buy = len(fav_buy_df[fav_buy_df.datetime_fav < fav_buy_df.datetime_buy].userid.value_counts())# process2 浏览->添加购物车->购买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_user_pv_cart = len(pv_cart_df[pv_cart_df.datetime_pv < pv_cart_df.datetime_cart].userid.value_counts())count_user_cart_buy = len(cart_buy_df[cart_buy_df.datetime_cart < cart_buy_df.datetime_buy].userid.value_counts())# 将数据合并成元组的列表是为了后面用pyecharts画图,如果不画图可以不这样合并process1 = [("浏览人数", count_users), ("收藏人数", count_user_pv_fav),("购买人数", count_user_fav_buy)]process2 = [("浏览人数", count_users), ("添加购物车人数", count_user_pv_cart),("购买人数", count_user_cart_buy)]conversion = pd.DataFrame(data=[[user[1] for user in process1], [user[1] for user in process2]], index=['process1', 'process2'], columns=['pv', 'fav/cart', 'buy'])conversion['pv_fav/cart'] = conversion['fav/cart'].div(conversion['pv'])conversion['fav/cart_buy'] = conversion['buy'].div(conversion['fav/cart'])conversion['pv_buy'] = conversion['buy'].div(conversion['pv'])

process1:用户转化率为9%,18%的用户会在浏览后收藏产品,其中只有47%的用户会购买该商品。

process2:用户转化率为23%,41%的用户会在浏览后把商品添加到购物车,其中有55%的用户会购买该商品。

从整个用户行为来看,89%的操作都只是在浏览,只有2%进行购买操作。

无论是从柱状图的高矮、漏斗图的粗细和数据比较我们都可以发现,process2的转化率更高,相较于收藏商品,用户更喜欢在购买商品前将商品放入购物车。

我们从淘宝app的设计来看一下,进入淘宝app后最底下一行很明显就有购物车的选择图标,而要进入收藏必须通过“我的淘宝->收藏夹”进行查看,多一步操作就多一种客户流失的可能性。再从两个界面进行考虑,加入购物车的商品很大概率会是用户已经选择好参数的商品(例如衣服尺寸、食品口味、3C产品配置等),点开购物车用户即可看到当初已经选择好的商品的现价(双11前夕我相信剁手党不可能只把商品收藏而不提前加入购物车吧);而收藏页面显示的只是商品概览(图片、标题、价格等),并没有用户自定义的参数选择,如若客户从收藏页进入再购买,势必又要多几步操作。

为什么用户更喜欢在购买前先将商品放入购物车,推测原因:

同款产品不同店铺比价凑单满减先放入购物车,等有优惠活动再购买

可以在商品详情页、商品图品等醒目地方添加提示用户将商品加入购物车的标语,或者添加限时优惠券,让顾客产生购买的紧迫感,刺激消费可能。

用户购买间隔分布

# 用户加入购物车后/收藏产品后多久会购买buy_after_cart = pd.DataFrame(cart_buy_df.datetime_buy-cart_buy_df.datetime_cart, columns=['interval'])buy_after_fav = pd.DataFrame(fav_buy_df.datetime_buy-fav_buy_df.datetime_fav, columns=['interval'])# 将timedelta格式转换为小时buy_after_cart['hours'] = buy_after_cart['interval'].map(lambda x: x.total_seconds()//3600)buy_after_fav['hours'] = buy_after_fav['interval'].map(lambda x: x.total_seconds()//3600)# 有些用户会先购买,再收藏/加入购物车,再次购买(按照数据来看真的会有这种用户),所以我们剔除这种先购买再收藏/加入购物车的操作记录# 即删除负值buy_after_cart = buy_after_cart[buy_after_cart['hours'] >= 0]buy_after_fav = buy_after_fav[buy_after_fav['hours'] >= 0]# 因为会出现大量的0小时,就是购买行为和添加购物车/收藏行为不满一小时# 所以我们加个1,这样理解起来就是两种操作是间隔一小时buy_after_cart['hours'] = buy_after_cart['hours']+1buy_after_fav['hours'] = buy_after_fav['hours']+1

无论是哪一种路径,用户在1小时之内购买的可能性都较大,其中收藏后购买的用户中有45%的用户在收藏后1小时内就下单购买,而加入购物车后再购买的时间间隔明显较长,添加购物车后购买的用户中有超过60%的用户在加入购物车12小时之后再进行购买。如有用户收藏或加入购物车后可有立即的客服跟进,例如优惠放送、话术吸引,则则很可能提高用户快速购买的可能性,进一步提高购买转化率。

每日情况

# 首先按照date进行分组import datetimegroupby_date = df.groupby(df.date)# 将日期字符串先转为日期格式days = pd.to_datetime(['/11/25', '/11/26', '/11/27', '/11/28','/11/29', '/11/30', '/12/01', '/12/02', '/12/03'])# 将日期作为索引daily_df = pd.DataFrame(data=None, columns=types, index=days)# 通过循环获得每组的统计数据for day in days:daily_df.loc[day] = groupby_date.get_group(day).type.value_counts()# 我们认为当天使用淘宝app进行3次操作(无论是查看详情页、收藏、加入购物车还是购买都算)的用户就是活跃用户# 自定义活跃用户操作次数基准active_user_standard = 3# 添加每日UVdaily_df['uv'] = [groupby_date.get_group(day).userid.nunique() for day in daily_df.index]# 根据date和userid分组后计算当天操作次数达到基准或以上的用户数作为活跃用户数daily_df['active_user'] = [(groupby_date.get_group(day).groupby(by='userid').size() > active_user_standard).value_counts()[True] for day in daily_df.index]# 活跃用户比例daily_df['active_user_rate'] = daily_df['active_user']/daily_df['uv']# 交易用户数daily_df['buyer'] = df[df['type'] == 'buy'][['date', 'userid']].groupby(by=['date', 'userid']).size().count(level=0)# 交易用户比例daily_df['buyer_rate'] = daily_df['buyer']/daily_df['uv']# 判断当天是周几daily_df['weekday'] = [datetime.datetime.isoweekday(datetime.date(x.year, x.month, x.day)) for x in daily_df.index]# 用户活跃天数temp = df[['userid', 'date', 'type']].groupby(by=['date', 'userid']).count()user_active_days_df = temp[temp['type'] > active_user_standard].count(level=1)sorted_user_active_df = user_active_days_df['type'].value_counts().sort_index()

每日的活跃用户量基本在70%上下浮动,而成交客户基本维持在20%。

浏览量、收藏数、添加购物车次数、购买次数、用户量在/12/02当天急速上升。周末的各项指标都优于周内,周六周日用户尤为活跃,用户有更多的时间可以逛淘宝,所以应当在周五晚间、周六周日当天进行适当的营销活动。

这9天内,用户活跃天数服从近似正态分布,用户活跃天数主要集中在3-7天(用户当天操作记录达3条算作当天活跃)。

时段情况

# 根据时段进行分组groupby_hour = df.groupby(by=df.hour)# 创建一个空的时段dataframe# 列表生成式创建一个0-23的时间列表times = [x for x in range(0, 24)]time_df = pd.DataFrame(data=None, index=times, columns=types)for t in times:time_df.loc[t] = groupby_hour.get_group(t).type.value_counts()time_df['uv'] = [groupby_hour.get_group(hour).userid.nunique() for hour in times]# 交易用户活跃时段groupby_hour_userid = df[df['type']=='buy'][['userid','hour']].groupby(by=['hour','userid'])buyer_hour = groupby_hour_userid.size().count(level=0)

各时段指标走势大致一致5:00-10:00及18:00-21:00两段时间是用户活跃度迅速增长的时段10:00-18:00这个时间段的用户活跃度上下浮动,但基本保持着同一水平。13:00,15:00这两个时间段是用户活跃度稳定阶段的两个小高峰,我们可以猜测13:00是因为用户工作午休结束了拿起手机再摸一会儿鱼造成的,15:00是因为工作了一两个小时又想摸鱼。17:00开始一部分用户下班了或马上下班,可以开始正大光明摸鱼21:00达到用户活跃度峰值

产品/类目情况

# 按照itemid进行分组groupby_itemid = df.groupby(by='itemid')item_type_df = groupby_itemid.type.value_counts().unstack()# 按照categroyid进行分组groupby_categoryid = df.groupby(by='categoryid')cat_type_df = groupby_categoryid.type.value_counts().unstack()# 热卖商品top10item_type_df.sort_values(by='buy', ascending=False)[:10]# 热销类目top10cat_type_df.sort_values(by='buy', ascending=False)[:10]

itemid为3122135、3031354等一些商品在这9天内属于热销产品,总订单量都在50单以上。1464116、2735466等类目的是这9天内销售量较高的类目。

# 一件商品在被购买前会经过多少次操作(多少次操作才能换来一次购买)item_type_df['behavior_transform'] = item_type_df.sum(axis=1)//item_type_df.buy

左上角属于快消/高频/品牌选择少/寡头左下角属于低频/贵重/品牌选择少/寡头右上角属于快消/高频/品牌选择多右下角属于决策慎重/低频/品牌选择多

大部分购买前累计行为发生在0-100次,购买次数集中在0-20次,用户喜欢购买的产品分类是属于左下角,要让分布逐渐往右上靠,从平台方考虑可以增加商品大类的专区假设,减少用户搜索对比,提升用户体验。若想让分布先往左上角移动可以考虑建设高频网红专区,或者在用户搜索时首先展示用户购买过或收藏过的品牌/产品。

两次操作就达成购买行为的计数很高(浏览一次就买),大多数购买前累计操作次数分布在0-100次,累计100次以上操作才换来一次购买行为的产品很多,如果有更详细的数据,例如在网页中埋点记录详情页留存率及用户浏览时长,就可以判断是在哪一阶段造成的用户流失或跳失率高的原因。

用户操作多,但是就不买,无外乎价格、质量、评价、产品介绍等方面,虽然说数据不可以成为“皇帝的新衣”,但是让用户产生购买“皇帝新衣”的冲动还是可以考虑的(满足一下客户小小的虚荣心)。

RFM模型

RFM模型是衡量客户价值和客户创利能力的重要工具和手段。在众多的客户关系管理(CRM)的分析模式中,RFM模型是被广泛提到的。该机械模型通过一个客户的近期购买行为、购买的总体频率以及花了多少钱3项指标来描述该客户的价值状况。

百度百科

重要价值客户最近消费时间近,消费频次和消费金额高,必须重点关注并保持住,需要提高用户满意度以及粘性。重要保持客户最近消费时间远,但消费频次和消费金额高,可以认为是有段日子没有来的忠诚客户,要主动与其联系,关注社群运营。重要发展客户最近消费时间近,消费金额高,频次低,用户忠诚度不高,但很可能是潜力客户,需要着重发展。重要挽留客户最近消费时间远,消费金额高,频次低,很可能成为流失用户,应该采取挽留措施。

在这就不多具体介绍这个模型了,因为数据集缺少交易额,所以这里就只能实现RF模型。

# R:Recency最近一次交易日期;F:Frequency频率,交易次数buy_userid_group = df[df['type'] == 'buy'].groupby(by='userid')# 先创建一个空的DataFrameRF = pd.DataFrame(index=buy_userid_group.groups.keys(), columns=['R', 'F'])# 因为这边索引的顺序就是按照groupby之后的顺序,所以直接赋值即可RF['F'] = buy_userid_group.type.value_counts().valuesRF['last_buy_time'] = buy_userid_group.datetime.max().values# 我们假设获取数据集的第二天进行分析,所以选择/12/04为对照日期,保留天数RF['R'] = (pd.to_datetime('-12-04')-RF['last_buy_time']).dt.days

def R_score(x):if 0 <= x <= 1:return 4elif 2 <= x <= 3:return 3elif 4 <= x <= 6:return 2elif 7 <= x <= 9:return 1else:return 0def F_score(x):if x == 1:return 1elif x == 2:return 2elif x == 3:return 3elif x >= 4:return 4else:return 0# 根据R,F进行评分RF['R_score'] = RF.R.map(R_score)RF['F_score'] = RF.F.map(F_score)

def user_classfication(tup):R_score, F_score = tupif R_score >= 3 and F_score > 2:return "重要保持客户"elif R_score >= 3 and F_score <= 2:return "重要发展客户"elif R_score < 3 and F_score > 2:return "重要价值客户"elif R_score < 3 and F_score <= 2:return "重要挽留客户"else:return NoneRF['user_classification'] = RF[['R_score', 'F_score']].apply(user_classfication, axis=1)

用户类型主要分布在走红要保持客户和重要发展客户,重要价值客户偏少,仅有7%,应该着重关注重要发展客户,提高其交易频次,转换为重要价值客户。

总结

12/02-12/03相较于其他日期用户活跃度、各指标增长明显,与同样是周末的11/25-11/26形成较大差距,猜测是该周末有运营促销活动相关(应该是临近双十二的预热活动)。5:00-10:00和8:00-21:00是用户活跃度迅速增长的时段,21:00-22:00是一天中用户最活跃时段,且下单量也是最高的,应着重在这个时间段进行营销推广活动。整体用户来看,人均购买次数为2次,而购买过商品的用户人均购买次数3次,复购率高达66%,应考虑拓宽获客渠道,保证产品质量、价格优势及维护老客的同时,要增加新用户量。付费用户相较于非付费用户多贡献了35.84%的PV,所以要对这些活跃用户建立深度的用户画像,进行更精准的商品推荐。55%的用户在加入购物车后会购买商品,实行适当的满减活动,刺激消费者购物车内比价,采取限时优惠券增加用户购买的紧迫感,促成购买行为。47%的用户在收藏后会购买产品,建议在用户收藏后能有优惠、促销提示,促使用户下单。用户在加入购物车或者收藏产品后的一小时内购买商品的概率是最高的,所以建议在用户有前两种操作时立刻有客服跟进,提供优惠放送、话术吸引,帮助用户决策,刺激用户快速下单购买。整体的用户行为转化率只有2%,98%的行为是没有转化为购买的,用户浏览详情页后即流失。建议封面及标题改进,进一步吸引用户提升浏览量,对活动提醒、优惠券及产品详情页进行适当调整,应更加醒目让用户产生购买冲动,以提高转化率。itemid为3122135的商品在9天内销售134单,在这份数据中是表现最好的,商家应该针对自己的热销产品建立粉丝群、微信群,实行社群管理,同时保证供应链畅通。大部分商品发生购买前累计用户行为在0-100次之间,要减少用户操作,提升客户购买效率及体验,例如对多次光顾店铺的顾客进行私信推荐、邀请进社群。根据RFM模型对用户分类后发现重要价值客户较少,用户类型主要分布在重要保持客户和重要发展客户。同样的,需要提高社群管理的效率,将重要保持客户和重要发展客户转变为重要价值客户。可采取定期发送文案、赠送优惠券等方式。要抓住用户渴望被认同、提升优越感、爱占便宜等心理进行考虑。

参考文献

数据分析-淘宝用户行为分析如何用mysql对淘宝用户行为进行分析淘宝APP用户行为数据分析案例(附python代码及注释)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。