Python数据分析实战项目——淘宝用户行为分析

目录

一、项目背景

二、数据收集

2.1 数据来源

2.2 数据信息

2.3 项目目标

2.3.1 分析目的

2.3.2 分析目标

三、数据读取与清洗

3.1 导入数据

3.2 重复值处理

3.3 缺失值处理

3.4 时间处理

四、 数据分析

4.1 用户行为分析

4.1.1 整体概况(UV、PV、平均访问量、交易总数、交易用户比例,复购率和跳失率)

4.1.1.1(UV、PV、平均访问量、交易总数、交易用户比例)

4.1.1.2 跳失率和复购率

4.1.2 用户转化漏斗分析

4.1.2.1 总体行为漏斗分析

4.1.2.2 独立访客行为漏斗分析

4.2 时间维度分析

4.2.1 用户行为时间维度分析

4.2.2 用户量时间维度分析

4.3 用户群体分类:RFM模型分析

4.4 商品分析

五、总结

5.1 用户行为分析

5.2  时间维度分析

5.3 RMF模型分析

5.4 商品维度分析


一、项目背景

UserBehavior是阿里巴巴提供的一个淘宝用户行为数据集,用于隐式反馈推荐问题的研究。数据集包含了2017年11月25日至2017年12月3日之间,有行为的约一百万随机用户的所有行为(行为包括点击、购买、加购、喜欢)。

构造推荐系统的关键资源是用户历史行为数据,具体可分为两类:显式反馈和隐式反馈。

显式反馈:直接表现用户的喜好倾向,如评分等。

优点:

  • 能提供更可靠的数据,不涉及从操作中提取偏好
  • 个性化程度足够高
  • 能够立即反馈给推荐系统

缺点:

  • 需要用户的努力,而用户不总有时间和兴趣提供足够的信息
  • 用户评分的主观性较强,会受到社会评价影响
  • 数据量较少

隐式反馈:不直接表现用户倾向的历史数据,如转发微博、浏览网站或购买商品等。

优点:

  • 从系统行为推断用户的偏好来减轻用户的负担
  • 隐形偏好数据相对更客观,用户不必以社会期望的方式做出回应,也没有自我形象问题或维护形象的需要
  • 数据量大

缺点:

  • 不太准确
  • 需要处理数据后才能反馈给推荐系统

二、数据收集

2.1 数据来源

https://tianchi.aliyun.com/dataset/649?t=1710751744909

2.2 数据信息

文件名称

说明

包含特征
UserBehavior.csv包含所有的用户行为数据用户ID,商品ID,商品类目ID,行为类型,时间戳

本数据集包含了2017年11月25日至2017年12月3日之间,有行为的约一百万随机用户的所有行为(行为包括点击、购买、加购、喜欢)。数据集的每一行表示一条用户行为,由用户ID、商品ID、商品类目ID1、行为类型和时间戳组成,并以逗号分隔。关于数据集中每一列的详细描述如下:

列名称说明
用户ID整数类型,序列化后的用户ID
商品ID整数类型,序列化后的商品ID
商品类目ID整数类型,序列化后的商品所属类目ID
行为类型字符串,枚举类型,包括('pv', 'buy', 'cart', 'fav')
时间戳行为发生的时间戳

用户行为类型共有四种,它们分别是

行为类型说明
pv商品详情页pv,等价于点击
buy商品购买
cart将商品加入购物车
fav收藏商品

2.3 项目目标

2.3.1 分析目的

用户角度:为用户推荐其真正感兴趣的商品,提高用户忠诚度。

网站角度:达到精准营销,提高成交转化率。

2.3.2 分析目标

1. 用户行为分析

        ①整体概况(PV,UV,复购率,跳失率等)

        ②用户转化漏斗分析

2. 时间维度分析--用户在哪些时间段活跃

        ①用户行为时段分析

        ②用户量时段分析

3. 商品分析--用户对哪些商品、类目感兴趣

        ①热门商品分析

        ②热门商品类目分析

4. 用户群体分类:RFM模型分析

三、数据读取与清洗

3.1 导入数据

首先导入数据,并根据对应列的描述给定列名,增强可读性;由于数据量过大,选取前100w行进行分析。

3.2 重复值处理

查看是否有重复值:无重复值。

3.3 缺失值处理

查看是否有空值:无空值。

查看每列的唯一值数量。

访问用户总数:9739

商品总数:399114

商品类目总数:5796

3.4 时间处理

将时间戳转为日期,由于数据集分析时间范围是2017-11-25至2017-12-03,剔除日期以外的数据。to_datetime不会处理时区问题,因此将Unix 时间戳转换为中国时区时间要加8小时,转换完成后保留2017-11-25至2017-12-03期间的数据,重置索引,接着按照日期和小时进行时间拆分,最后删除时间戳。

四、 数据分析

4.1 用户行为分析

4.1.1 整体概况(UV、PV、平均访问量、交易总数、交易用户比例,复购率和跳失率)

4.1.1.1(UV、PV、平均访问量、交易总数、交易用户比例)

可以得到:

独立访问用户总数(UV):9739

页面总访问量(PV):895636

平均访问量(PV/UV):四舍五入后91

交易总数:20359

交易用户比例:68.68%

可看到用户数为9739,但是总访问量有895636,说明每个用户平均点击访问约91次,并且交易用户比例为68.68%,超过总用户的一半以上,说明商品对用户的吸引力较高。

4.1.1.2 跳失率和复购率

跳失率

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

首先将数据按照用户id分组,然后对分组后的数据统计每个用户的type列的不同值的出现次数,将结果转换成新表,就可以通过将每个id的横向数据相加和与单点击数据进行对比,找出只有点击行为的用户。

跳失率为5.82%,数值较低,但跳失率从一定程度上反映了商品的受欢迎程度,可以结合行业数据与历史数据分析是否处于正常范围。一般影响跳失率的因素包括商品吸引力,加载时长等等。

复购率

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

复购率为66.21%,可以看出用户忠诚度较高。

总结:结合复购率和跳失率来看,淘宝的商品质量高,可以持续吸引用户,因此在扩展获取新用户的同时,可以更加关注促进老用户复购次数增加,进一步稳定提高复购率。商品购买一次可能是被营销活动或者吸睛的标题和图片所吸引,但是复购就要求商品质量优秀、消费服务体验良好,淘宝可以在这些方面帮助商家留住客户。

4.1.2 用户转化漏斗分析

漏斗分析是一套流程式数据分析,它能够科学反映用户行为状态以及从起点到终点各阶段用户转化率情况的重要分析模型,可以帮助决策者找到用户流失的原因,以提升用户量、活跃度、留存率,并提升数据分析与决策的科学性等。

4.1.2.1 总体行为漏斗分析

由于本数据集特征有限,所以分析两条路径:点击 - 收藏 - 购买;点击 - 加购 - 购买

数据上面已经得到,如下所示:

使用Excel转化图表可视化如下图:

用户浏览详情页后,点击加购或者收藏的百分比在9.3%左右,最后支付的百分比为2.3%左右,第二步到第三部剩余四分之一左右,但第一步到第二步仅剩9.3%,说明用户在浏览详情页以后大量流失,应提高用户点击到收藏和加购的转化率。

4.1.2.2 独立访客行为漏斗分析

接下来可以分析独立访客UV的转化漏斗

使用Excel进行可视化后的图表如下:

以独立访客为分析维度可以看出,用户在点击之后并未大量流失,75%的用户选择了将商品加入购物车,40%的用户选择了收藏,最后有68.92%的用户选择了支付购买,整体的转化率较高,说明整体生态健康,可以满足大多数用户的需求。

总结:综合以上两个分析,虽然整体上点击量到购买量的转化率低,但是从独立用户维度来看,点击到购买的转化率还是比较高的,原因可能是:①用户在购买之前会对商品进行大量对比,在对比之后产生购买意向,最后购买。②用户被自身没有需求的促销商品或吸睛标题所吸引,虽然不打算购买也会点击查看。可以从这两方面入手,以用户日常行为作为依据,尽量进行精准推荐,没有精准推荐商品时可推荐促销商品或热门商品,增加商品流量,从而提高购买转化率。

4.2 时间维度分析

4.2.1 用户行为时间维度分析

用户行为变化趋势:

点击量、收藏量、购买量在12/02号有显著上升,12/02和11/25都是周六,但是12/02当天的点击量上升更加显著,原因是:2017/12/02当天淘宝开始为“双十二”活动进行预热,开启商品精选活动,此活动吸引了更多的点击量。

此外星期天的各项数据都优于工作日,说明周六周日用户有更多的时间逛淘宝,并且愿意花时间去点击浏览更多商品,所以在周六周日进行营销活动效果会更好。

4.2.2 用户量时间维度分析

用户行为时间段分布:

5:00-10:00和18:00-21:00两个时间短是用户活跃度迅速增长的时段;

12:00和17:00用户活跃度有小幅下降,可能是受上班上学人群作息规律影响;

10:00-18:00这个时间段的用户活跃度虽然有所波动,但整体水平保持稳定;

21:00用户活跃度达到一天内的峰值,可以考虑在18:00-21:00进行营销活动提升转化率,例如直播带货、拼单促销等。

4.3 用户群体分类:RFM模型分析

RFM模型通过一个客户的近期购买行为、购买的总体频率以及花了多少钱3项指标来描述该客户的价值状况。

R(Recency):客户最近一次交易时间的间隔。R值越大,表示客户交易发生的日期越久,反之则表示客户交易发生的日期越近。

F(Frequency):客户在最近一段时间内交易的次数。F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。

M(Monetary):客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。

本次分析数据集不含金额,因此仅从R、F两个维度进行分析。

 可以看出最近的一次交易记录距离2017/12/04为0天,即12/03购买相差还不到一天,最远的为8天,平均为2.52天,R我们划分4个区域 0-1,2-3,4-6,7-8分别得分4,3,2,1。

交易次数最少为1次最多为72次,平均3次,这里的平均3次分母是所有购买过商品的用户,F划分4个区域 1-9,10-19,20-29,30-39,40-49,50+,分别得分1,2,3,4,5,6。

重要保持客户:近期购买间隔较长但频率较高客户

重要发展客户:近期购买间隔较短但频率较低客户

重要价值客户:近期购买间隔较短且频率较高客户

重要挽留客户:近期购买间隔较长且频率较低客户

根据RFM模型对用户分类发现重要挽留客户比例最高,说明该部分客户存在很大的待挖掘潜在价值,应对其进行调研,分析其流失原因,对其进行活动推送或发放优惠券进行召回;其次是重要价值用户,该部分群体价值极高,应当尽力保持维护,保证较高的用户粘性;重要发展客户可以对其进行精准推送从而留住客户;重要保持客户占比较低,可对其进行定期推送、上新通知等。

4.4 商品分析

商品销量分析

分析指标:销量前十的种类categoryid,销量前十的商品itemid

结论:在购买率前十的商品中,可以观察到单件商品最高购买量也只有17,前五件商品购买量超过10,说明没有爆款热销商品存在,主要靠商品多样化满足用户需求,所以可以从商品多样化和爆款热销商品两方面入手提高转化率。

2964774和3563468两件商品点击量远远超过其他商品,但是购买率却很低,可以分析吸引用户点击量的原因,从而留住用户;其他商品有些虽然点击量不高,但是点击购买转化率却很高,也许是某些特定群体需要,可以分析用户画像,如果是特定群体购买更多,就可以集中像此群体用户多推送,如果不是特定群体的需求可以加强宣传推广,提高点击量,从而带动购买量。

结论:在购买率前十的商品类目中,点击购买转化率都很低,原因可能是因为同一商品类目中包含很多商品,用户会进行大量对比挑选,最后购买具体的一个商品。可以通过用户的历史行为推测用户的感兴趣商品类目,从中挑选性价比较高或者销售较多的商品推送给用户,减少用户的对比,从而提高转化率。

五、总结

5.1 用户行为分析

根据独立用户维度来看,用户的点击购买转化率较高,但是从整体来看,点击量到购买量的转化率很低,说明用户在点击之后并不一定会购买,在进行大量商品浏览对比之后,才会有购买意向。但是从加入购物车或收藏到购买的较高转化率来看,可以引导用户增强收藏/加入购物车的习惯,从而提高购买率。根据跳失率和复购率来看,用户整体粘性较高,商品具有足够的吸引力并且可以满足用户的需求。可以收集用户画像,进行精准推送,并对用户进行精心维护,减少流失。

5.2  时间维度分析

根据日期维度来看,用户在休息日相对更加活跃,并且会受到营销活动影响。根据时间维度来看,用户的活跃时间在10:00-22:00,并且在21:00达到高峰,说明利用下午或晚上进行营销活动效果较好,进行直播带货或者优惠活动用来提高用户活跃度和转化率。

5.3 RMF模型分析

根据交易间隔和交易频率来对用户群体进行划分分成四个群体:重要保持客户、重要发展客户、重要价值客户、重要挽留客户。根据不同群体标签采取不同的运营策略。

重要保持客户和重要挽留客户:调研用户流失原因,关注用户的购物习惯,挖掘潜在价值,提升购买意愿。

重要发展客户:定期为其推送活动或上新商品,增加其购买频率。

重要价值客户:重点关注维护,为其提供专属客服和优惠折扣提高满意度,保证用户粘性。

5.4 商品维度分析

根据销售前十商品和商品类目来看,单件商品最高购买量不超过17,但是点击购买转化率较高,说明有销售潜力,只是缺少点击量,可以进行精准营销推送或大力推广宣传增加点击量;部分点击量高但转化率低的商品分析具体原因,增加其转化率。其次在增加商品多样性的同时可以尝试打造爆款热销商品,在提高点击量的同时提升转化率。

源代码如下:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from pyecharts.globals import CurrentConfig, NotebookType
from pyecharts import options as opts
from pyecharts.charts import Line
from pyecharts.charts import Bar

CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_NOTEBOOK

columns=["userid", 'itemid', 'categoryid', 'type', 'timestamp']
data = pd.read_csv('UserBehavior.csv',
                   engine='python',
                   encoding='utf-8',
                   names=columns,
                   chunksize=1000000,
                   iterator=True)
dataframe = data.get_chunk(1000000)
dataframe.info()
dataframe.isnull().sum()
dataframe.nunique()

# 时间戳的数据类型是float64,要转换为日期类型
import datetime

# 时区转换to_datetime的默认时区不是中国,所以要加8小时
dataframe['time']=pd.to_datetime(dataframe['timestamp'],unit='s')+datetime.timedelta(hours=8)

# 保留2017.11.25-2017.12.3期间的数据
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

# 删除时间戳节约内存
dataframe.drop('timestamp', inplace=True, axis=1)

pd.set_option("float_format", lambda x: "%.2f" % x)                      # 取消科学计数法,保留两位小数
# 9天总用户量,有操作的商品及商品类目
total_unique_users = dataframe.userid.nunique()                          # 独立访客数UV
total_unique_itemid = dataframe.itemid.nunique()                         # 有操作的商品
total_unique_categoryid = dataframe.categoryid.nunique()                 # 有操作的商品类目
user_bought_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_bought_count/total_unique_users*100:.2f}%")


type_series = dataframe.type.value_counts()
print(type_series)
plt.figure()
plt.pie(x=type_series,labels=type_series.index,autopct='%1.2f%%')
plt.show()

# 9日内各个行为的操作总数,每日平均操作数,每日平均操作用户数记录
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进行不堆叠操作,列方向上的索引转成行方向的索引
user_type.tail()


# 跳失率
# sum(axis=1)对DataFrame进行横向相加,如果一个userid的pv值==横向相加的和,那就表明他只有点击行为
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))

# 复购率
repurchase_users = user_type[user_type['buy']>=2].shape[0]  # 购买记录超过1次的用户数
repurchase_rate = repurchase_users/user_bought_count
print("复购率:{:.2f}%".format(repurchase_rate*100))

# 进一步分析复购次数
sns.distplot(user_type[user_type['buy']>=2]['buy']-1,kde=False)
plt.show()

user_pv_count = dataframe[dataframe['type']=='pv'].userid.nunique()  # 点击用户数
user_cart_count = dataframe[dataframe['type']=='cart'].userid.nunique()  # 加购用户数
user_fav_count = dataframe[dataframe['type']=='fav'].userid.nunique()  # 收藏用户数
user_bought_count = dataframe[dataframe['type']=='buy'].userid.nunique()  # 付费用户数
print(f'点击用户数:{user_pv_count}')
print(f'加购用户数:{user_cart_count}')
print(f'收藏用户数:{user_fav_count}')
print(f'付费用户数:{user_bought_count}')


behavior_types=list(dict(dataframe['type'].value_counts()).keys())
behavior_types
groupby_date = dataframe.groupby(by=dataframe.date)                               # 根据日期分组
dates = sorted(list(dict(dataframe['date'].value_counts()).keys()))
dates_df = pd.DataFrame(data=None, index=dates, columns=behavior_types)           # 创建按日期分组的数据框

for d in dates:
    dates_df.loc[d] = groupby_date.get_group(d).type.value_counts()               # 按日期填充数据框

# 日期转换为星期,datetime.datetime.isoweekday()返回的1-7代表周一--周日
dates_df['weekday'] = [datetime.datetime.isoweekday(datetime.date(x.year,x.month,x.day)) for x in dates_df.index]
dates_df

dates_df.plot(rot=60)
plt.show()


groupby_hour = dataframe.groupby(by='hour')                                         # 根据时段分组
hours = [x for x in range(0, 24)]
hours_df = pd.DataFrame(data=None, index=hours, columns=behavior_types)

for h in hours:
    hours_df.loc[h] = groupby_hour.get_group(h).type.value_counts()

hours_df['uv'] = [groupby_hour.get_group(hour).userid.nunique() for hour in hours]  # 独立访客量

hours_df.plot(rot=60)
plt.show()



# R:Recency最近一次交易日期间隔;F:Frequency频率,交易次数
groupby_buy_userid = dataframe[dataframe['type']=='buy'].groupby(by='userid')
# 先创建一个空的DataFrame
RF = pd.DataFrame(index=groupby_buy_userid.groups.keys(), columns=['R', 'F'])

RF['F'] = groupby_buy_userid.type.count()
RF['last_buy_time'] = groupby_buy_userid.time.max()
# 假设获取数据集的第二天进行分析,所以选择2017/12/04为对照日期,保留天数
RF['R'] = (pd.to_datetime('2017-12-04')-RF['last_buy_time']).dt.days
RF[['R','F']].describe()


def R_score(x):
    if 0 <= x <= 1:
        return 4
    elif 2 <= x <= 3:
        return 3
    elif 4 <= x <= 6:
        return 2
    else:
        return 1


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


# 根据R,F进行评分
RF['R_score'] = RF.R.map(R_score)
RF['F_score'] = RF.F.map(F_score)
RF['R>mean?']=(RF['R_score']>RF['R_score'].mean())*1
RF['F>mean?']=(RF['F_score']>RF['F_score'].mean())*1

def user_classfication(tup):
    R_score, F_score = tup
    if R_score == 0 and F_score == 1:
        return "重要保持客户"
    elif R_score == 1 and F_score == 0:
        return "重要发展客户"
    elif R_score == 1 and F_score == 1:
        return "重要价值客户"
    elif R_score == 0 and F_score == 0:
        return "重要挽留客户"
    else:
        return None
    
RF['user_classification'] = RF[['R>mean?','F>mean?']].apply(user_classfication, axis=1)

# 统计用户分类情况
RF.user_classification.value_counts()

# 用户分类占比
RF.user_classification.value_counts(1)

groupby_itemid = dataframe.groupby(by='itemid')                               # 按商品分组
item_type_df = groupby_itemid.type.value_counts().unstack()                   # 展开为一个dataframe
item_type_df.replace(to_replace=np.nan, value=0, inplace=True)                # 缺失值补0
item_type_df = item_type_df.sort_values(by='buy', ascending=False)            # 按购买量降序排列

item_type_df.head(10)

groupby_categoryid = dataframe.groupby(by='categoryid')
category_type_df = groupby_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.head(10)


  • 17
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值