飞猪平台用户行为分析—python

发布时间:2024-09-01 11:01

文章目录

  • 一、项目背景
    • 1.1数据来源
    • 1.2数据介绍
  • 二、分析目的
  • 三、分析思路
  • 四、数据分析
    • 3.1数据清洗
    • 3.2用户分析
      • 3.2.1用户维度
        • 3.2.1.1浏览量pv、访客量uv、成交量分析
        • 3.2.1.2留存分析
        • 3.2.1.3用户画像
      • 3.2.2行为维度
        • 3.2.2.1复购率和跳失率
        • 3.2.2.2漏斗分析
        • 3.2.2.3用户行为在时间上的分布
    • 3.3 商品分析
      • 3.3.1热门商品分析
      • 3.3.2购买路径分析
      • 3.3.3商品画像
  • 五、总结


提示:本项目分析仅用来学习使用

一、项目背景

作为中国最受欢迎的在线旅游平台(OTP)之一,阿里巴巴集团旗下的飞猪通过提供百万级旅游相关产品(如机票、酒店、旅行团、 ETC)。平台拥有庞大的产品组合,平台积累用户的行为数据,该数据集是用户脱敏行为数据,包含基本属性用户信息和商品基本属性的脱敏信息。

1.1数据来源

阿里云天池数据集:飞猪出行平台用户行为数据推荐

1.2数据介绍

数据由三部分组成:用户历史行为脱敏数据、用户基础属性脱敏数据、商品基础属性脱敏数据。
\"飞猪平台用户行为分析—python_第1张图片\"
行为类型:(\'clk\', \'fav\', \'cart\',\'pay\')

user_item_behavior_history.csv

该数据集涵盖了2019年6月3日至2021年6月3日这两年期间约200万随机用户的所有行为(包括点击、收藏、添加和购买)。数据集的组织类似于MovieLens-20M,即每一行集合代表一个用户数据行为,由用户ID、产品ID、行为类型、日志组成。每列总结了被调查产品的详细信息。

原数据集共2亿多数据,本项目只选取了2021年5月3日至2021年6月3日一个月接近8000,000的数据。

user_profile.csv

该数据集主要包含约五百万随机用户的基本属性,如年龄、性别、职业、居住城市ID、人群标签等。数据集的每一行代表一条用户信息,以逗号分隔。

item_profile.csv

该数据文件主要包含约27万个产品的基本属性特征,如产品类别ID、产品城市、产品标签等。数据集的每一行代表一个产品的信息,以逗号分隔。


二、分析目的

目标是从用户的行为数据中挖掘当前用户的行为特征,通过分析这些特征能够发现平台当前所面临的一些问题并分析原因,从而能出台一些针对性的解决措施,扩大用户的使用转化率。


三、分析思路

  1. 用户维度

    -pv/uv/pay:总量、平均人均(日期、时刻、星期)

    -留存分析:次日、三日、五日、七日、十五日、三十日(用户粘度)

    -用户画像:年龄、性别、职业、区域分布

  2. 行为维度

    -复购率和跳失率情况

    -用户行为转化率情况

    -用户行为在时间上的分布

  3. 商品维度

    -热门商品分析:点击、收藏、加购、购买前十

    -商品购买路径分析:点击、收藏、加购——购买(转换率分析)

    -商品画像:种类、地域、标签分布


四、数据分析

3.1数据清洗

导入数据’user_item_behavior_history.csv’

# 增加列名\'user_id\', \'item_id\', \'behavior_type\',\'timestamp\'
reader = pd.read_csv(\'./data/user_item_behavior_history.csv\', header=None, names = [\'user_id\', \'item_id\', \'behavior_type\',\'timestamp\'], iterator=True)

# 使用get_chunk方法获取数据
loop = True
chunkSize = 10000000  # 设置chunksize
chunks = []

import datetime
# start time
starttime = datetime.datetime.now()

# long running
while loop:
    try:
        chunk = reader.get_chunk(chunkSize)
        chunks.append(chunk)
    except StopIteration:
        loop = False
        print(\"Iteration is stopped.\")  # 迭代完成
# 拼接chunks        
df = pd.concat(chunks, ignore_index=True)

# end time
endtime = datetime.datetime.now()

# 共计数据获取时间
print(\'loop_time:\', (endtime - starttime).seconds)

\"飞猪平台用户行为分析—python_第2张图片\"
原数据共计获取时间为304秒,也就是5分钟左右,数据共计2亿多行。

# timestamp转为datetime
df[\'timestamp\'] = pd.to_datetime(df[\'timestamp\'], unit=\'s\')
# 查看前五行数据
df.head()

\"飞猪平台用户行为分析—python_第3张图片\"
获取分析数据

start_date = pd.to_datetime(\'20210503\', format=\'%Y-%m-%d %H:%M:%S\') # 开始日期
end_date = pd.to_datetime(\'20210604\', format=\'%Y-%m-%d %H:%M:%S\') # 截止时间
df = df[(df[\'timestamp\'] >= start_date) & (df[\'timestamp\'] <= end_date)]
df = df.sort_values(by=\'timestamp\', ascending=True) # 时间按升序排列
df = df.reset_index(drop=True) # 重置索引

\"在这里插入图片描述\"
分析的数据共计7,983,450行

\"飞猪平台用户行为分析—python_第4张图片\"
由此可见,此时的数据没有缺失值和异常值;
而重复数据在这里是正常的,因为用户是可能在同一时间进行多次相同行为的,所以对重复数据不做处理。

# 把列\'nehavior_type\'中的\'clk\',\'fav\',\'cart\',\'pay\'替换为1,2,3,4
\'\'\'
1——点击
2——收藏
3——加购
4——购买
\'\'\'
replace_values = {\'clk\':1, \'fav\':2, \'cart\':3, \'pay\':4}
df[\'behavior_type\'] = df[\'behavior_type\'].replace(replace_values)
# 时间格式转换,获取日期、时间、年、月、日、周几、小时
df[\'date\'] = df[\'timestamp\'].dt.date
df[\'time\'] = df[\'timestamp\'].dt.time
df[\'year\'] = df[\'timestamp\'].dt.year
df[\'month\'] = df[\'timestamp\'].dt.month
df[\'day\'] = df[\'timestamp\'].dt.day
df[\'weekday\'] = df[\'timestamp\'].dt.strftime(\"%w\")
df[\'hour\'] = df[\'timestamp\'].dt.hour

\"飞猪平台用户行为分析—python_第5张图片\"

3.2用户分析

从用户维度和行为维度两个维度去分析

3.2.1用户维度

3.2.1.1浏览量pv、访客量uv、成交量分析

总量

uv = df[\'user_id\'].nunique() # 用户数量uv
item_num = df[\'item_id\'].nunique() # 商品数量
behavior_num = df[\'behavior_type\'].count() # 行为总数

\"飞猪平台用户行为分析—python_第6张图片\"

clk_data = df[df[\'behavior_type\'] == 1] # 点击数据
fav_data = df[df[\'behavior_type\'] == 2] # 收藏数据
cart_data = df[df[\'behavior_type\'] == 3] # 加购数据
pay_data = df[df[\'behavior_type\'] == 4] # 支付数据

\"在这里插入图片描述\"
由以上得到的数据可以知道:点击>加购>收藏>支付
所以转化路径应为:点击—加购—收藏—支付

这里的点击clk相当于浏览pv

page_view = len(clk_data) # 总浏览量
pay_num = len(pay_data) # 总支付量
pv_avg = round(page_view/uv, 2) # 总平均浏览量
pay_avg = round(pay_num/uv, 2) # 总平均支付量

\"飞猪平台用户行为分析—python_第7张图片\"
在这一个月内,总体来看,在1005061个用户中,平均每个人浏览7.19次,支付率为22%,说明用户活跃度不高且支付转化率不高。

日均

# 日访问量
pv_daily = clk_data.groupby(\'date\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pv_daily\'})
# 日访客量
uv_daily = df.groupby(\'date\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'uv_daily\'})
# 拼接
daily_data = pd.merge(pv_daily, uv_daily, how=\'outer\', on=\'date\')
# 日平均访问量
daily_data[\'avg_pv_daily\'] = round(daily_data[\'pv_daily\']/daily_data[\'uv_daily\'], 2)

\"飞猪平台用户行为分析—python_第8张图片\"

# 日成交量
pay_daily = pay_data.groupby(\'date\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pay_daily\'})
# 拼接
daily_data = pd.merge(daily_data, pay_daily, on=\'date\')
# 日平均成交量
daily_data[\'avg_pay_daily\'] = round(daily_data[\'pay_daily\']/daily_data[\'uv_daily\'], 2)

\"飞猪平台用户行为分析—python_第9张图片\"

# 创建图形
fig = plt.figure(figsize=(20,8),dpi=80)
plt.grid(True, linestyle=\"--\", alpha=0.5)
ax1 = fig.add_subplot(111)
ax1.plot(daily_data.date, daily_data.avg_pv_daily, label=\'日平均访问量\')
ax1.set_ylabel(\'日平均访问量\')
ax1.set_title(\'daily_data\', size=15)
ax1.legend(loc=\'upper left\')
ax2 = ax1.twinx() # 共享x轴
ax2.plot(daily_data.date, daily_data.avg_pay_daily, \'r\', label=\'日平均成交量\')
ax2.set_ylabel(\'日平均成交量\')
ax2.set_xlabel(\'日期\', size=15)
ax2.legend(loc=\'upper right\')
plt.show()

\"飞猪平台用户行为分析—python_第10张图片\"
每天的人均访问量从上半月急剧下滑,到下半月持续走低,直至月底31号跌倒谷底,然后又突然上升;
每天的人均成交量从月初直线下降,然后缓慢回升,直至月底31号达到顶峰,随后突然回落。

时均

# 每小时访问量
pv_hour = clk_data.groupby(\'hour\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pv_hour\'})
# 每小时访客量
uv_hour = df.groupby(\'hour\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'uv_hour\'})
# 拼接
hour_data = pd.merge(pv_hour, uv_hour, how=\'outer\', on=\'hour\')
# 每小时平均访问量
hour_data[\'avg_hour_pv\'] = round(hour_data[\'pv_hour\']/hour_data[\'uv_hour\'], 2)

\"飞猪平台用户行为分析—python_第11张图片\"

# 每小时成交量
pay_hour = pay_data.groupby(\'hour\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pay_hour\'})
# 拼接
hour_data = pd.merge(hour_data, pay_hour, on=\'hour\')
# 每小时平均成交量
hour_data[\'avg_hour_pay\'] = round(hour_data[\'pay_hour\']/hour_data[\'uv_hour\'], 2)

\"飞猪平台用户行为分析—python_第12张图片\"

# 创建图形
fig = plt.figure(figsize=(20,8),dpi=80)
plt.grid(True, linestyle=\"--\", alpha=0.5)
ax1 = fig.add_subplot(111)
ax1.plot(hour_data.hour, hour_data.avg_hour_pv, label=\'每小时平均访问量\')
ax1.set_ylabel(\'每小时平均访问量\')
ax1.set_title(\'hour_data\', size=15)
ax1.legend(loc=\'upper left\')
ax2 = ax1.twinx() # 共享x轴
ax2.plot(hour_data.hour, hour_data.avg_hour_pay, \'r\', label=\'每小时平均成交量\')
ax2.set_ylabel(\'每小时平均成交量\')
ax2.set_xlabel(\'时刻\', size=15)
ax2.legend(loc=\'upper right\')
plt.show()

\"飞猪平台用户行为分析—python_第13张图片\"
每时刻的人均访问量从零点开始上升,在凌晨3点之后缓慢回落,在12点之后又开始一直上升,直至下午2点达到顶点,之后急剧下降;
每时刻的人均成交量从零点开始上升,在凌晨3点达到顶点,之后不断回落,在中午12点之后急剧下滑。

周均

pv_weekday = clk_data.groupby(\'weekday\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pv_weekday\'})
uv_weekday = df.groupby(\'weekday\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'uv_weekday\'})
weekday_data = pd.merge(pv_weekday, uv_weekday, how=\'outer\', on=\'weekday\')
weekday_data[\'avg_pv_weekday\'] = round(weekday_data[\'pv_weekday\']/weekday_data[\'uv_weekday\'], 2)

\"飞猪平台用户行为分析—python_第14张图片\"

pay_weekday = pay_data.groupby(\'weekday\')[\'user_id\'].count().reset_index().rename(columns={\'user_id\': \'pay_weekday\'})
weekday_data = pd.merge(weekday_data, pay_weekday, on=\'weekday\')
weekday_data[\'avg_pay_weekday\'] = round(weekday_data[\'pay_weekday\']/weekday_data[\'uv_weekday\'], 2)

\"飞猪平台用户行为分析—python_第15张图片\"
人均访问量最高是周一,最低是周日;
人均支付量最高是周一,最低是周四和周五。

总结

  • 用户在31日人均成交量和人均访问量分别达到最高和最低;
  • 用户在凌晨比较活跃,人均成交量高,凌晨两点左右人均成交量最高,下午三点人均访问量最高;
  • 周一时的人均成交量和人均访问量同时达到最高;
  • 经查询日历,发现2021年5月31日正好是周一,所以可以猜测应该是由于6月份有‘618’活动,活动力度和优惠力度较大,需要在6月之前下单完成,所以用户在活动结束前5.31集中进行购买之前已经收藏和加购好的商品,很少再进行浏览;
  • 总体用户的活跃度和支付转化率较低。

3.2.1.2留存分析

次日留存率=(某日新增的用户中,在注册的第2天还进行登录的用户数)/ 该日新增用户数

3日留存率=(某日新增用户中,在注册的第3天还进行登录的用户数)/ 该日新增用户数

7日留存率=(某日新增的用户中,在注册的第7天还进行登录的用户数)/ 该日新增用户数

30日留存率=(某日新增的用户中,在注册的第30天还进行登录的用户数)/ 该日新增用户数

# 创建n日留存函数
def cal_retention(data, n):  # n为n日留存
    user = []
    date = pd.Series(data.date.unique()).sort_values()[:-n] # 时间截取至最后一天的前n天
    retention_rates =[]
    for i in date:
        new_user = set(data[data.date == i].user_id.unique()) - set(user) # 识别新用户,设初始用户量为零
        user.extend(new_user)
        # 第n天留存状况
        user_nday = data[data.date == i+timedelta(n)].user_id.unique() # 第n天登陆的用户状况
        a = 0
        for user_id in user_nday:
            if user_id in new_user:
                a += 1
        retention_rate = a/len(new_user) # 计算该天第n日留存率
        retention_rates.append(retention_rate) # 汇总n日留存数据
    data_retention = pd.Series(retention_rates, index=date)
    return data_retention
# 分别计算留存率
retention_2days = cal_retention(df, 1).apply(lambda x: format(x, \'.2%\'))   # 次日留存
retention_3days = cal_retention(df, 2).apply(lambda x: format(x, \'.2%\'))   # 3日留存
retention_7days = cal_retention(df, 6).apply(lambda x: format(x, \'.2%\'))   # 7日留存
retention_15days = cal_retention(df, 14).apply(lambda x: format(x, \'.2%\'))   # 15日留存
retention_30days = cal_retention(df, 29).apply(lambda x: format(x, \'.2%\'))   # 30日留存
# 留存拼接
retention_data = pd.concat([retention_2days, retention_3days, retention_7days, retention_15days, retention_30days], axis=1)
# 改变列名
retention_data.columns = [\'次日\', \'3日\', \'7日\', \'15日\', \'30日\']
retention_data = retention_data.replace(np.nan, \'\')
print(retention_data)
# 存入CSV
retention_data.to_csv(\'retention.csv\', encoding=\'utf_8_sig\')

\"飞猪平台用户行为分析—python_第16张图片\"
从不同的时间来看,留存率整体是比较低的,但这也可能跟多数用户出行频率不高的原因有关;
从另一个方面,可以加大活动优惠,提升产品品质,增强用户粘度。

3.2.1.3用户画像

只对支付用户进行分析

# 支付用户的消费时间
payuser_date = pay_data[[\'user_id\', \'hour\', \'weekday\']]

时刻

# 支付用户按小时分布
payuser_hour = payuser_date.groupby(\'hour\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
# 创建图形
plt.figure(figsize=(20,8), dpi=80)
plt.bar(payuser_hour.hour, payuser_hour.num, label=\'每小时成交量\')
plt.plot(payuser_hour.hour, payuser_hour.num, \'ro-\', color=\'r\', alpha=0.8, linewidth=3)

# 添加标注
plt.xlabel(\'小时\',size=15)
plt.ylabel(\'成交量\',size=15)

#添加标题
plt.title(\'支付用户按小时分布\',size=15)

# 添加图例
plt.legend(loc=\'best\')

# 显示柱状-折线图
plt.show()

\"飞猪平台用户行为分析—python_第17张图片\"
用户主要喜欢在凌晨支付,尤其是凌晨两点,在晚上支付最低,分析可能是用户在晚上时间主要在浏览选择自己感兴趣的东西,然后在凌晨才能下定决心支付,越晚越容易‘冲动’哈哈~

星期

# 支付用户按周几分布
payuser_weekday = payuser_date.groupby(\'weekday\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
print(payuser_weekday)
# 创建图形
plt.figure(figsize=(10,5), dpi=80)
plt.bar(payuser_weekday.weekday, payuser_weekday.num, label=\'每周几成交量\')

# 添加标注
plt.xlabel(\'星期\',size=15)
plt.ylabel(\'成交量\',size=15)

#添加标题
plt.title(\'支付用户按星期分布\',size=15)

# 添加图例
plt.legend(loc=\'best\')

# 显示柱状图
plt.show()

\"飞猪平台用户行为分析—python_第18张图片\"
用户喜欢在周一支付,可能跟5.31是星期一有关。

# 读取user_profile.csv,并增加列名\'user_id\',\'age\',\'sex\',\'career\',\'use_city_id\',\'crowd_label\'
user_profile = pd.read_csv(\'./data/user_profile.csv\', header=None, names = [\'user_id\',\'age\',\'sex\',\'career\',\'use_city_id\',\'crowd_label\'], encoding=\'utf-8\')
# 根据user_id拼接user_profile数据
payuser_profile = pd.merge(payuser_date, user_profile, how=\'left\', on=\'user_id\')

年龄

# 最大年龄及最小年龄
print(payuser_profile[\'age\'].max(), payuser_profile[\'age\'].min())

\'\'\'
考虑到平台注册年龄限制,所以最小年龄设置为18岁;
对年龄异常数据进行处理;
\'\'\'
payuser_profile = payuser_profile[payuser_profile[\'age\']>=18]
print(payuser_profile[\'age\'].min())

# 年龄分箱
bins = [18,25,35,45,60,80,125]
labels = [\'[18-25)\',\'[25-35)\',\'[35-45)\',\'[45-60)\',\'[60-80)\',\'[80-125]\']
payuser_profile[\'age_cut\'] = pd.cut(x=payuser_profile.age, bins=bins, right=False, labels=labels)
print(payuser_profile.head())

# 年龄分布
payuser_age = payuser_profile[[\'user_id\', \'age_cut\']].groupby(\'age_cut\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
print(payuser_age)
# 创建图形
plt.figure(figsize=(10,5), dpi=80)
plt.bar(payuser_age.age_cut, payuser_age.num, label=\'年龄段成交量\')

# 添加标注
plt.xlabel(\'年龄\',size=15)
plt.ylabel(\'成交量\',size=15)

#添加标题
plt.title(\'支付用户按年龄段分布\',size=15)

# 添加图例
plt.legend(loc=\'best\')

# 显示柱状图
plt.show()

\"飞猪平台用户行为分析—python_第19张图片\"
支付用户的年龄主要集中在45~60岁年龄段,这个年龄的用户在退休年龄左右,相对年轻人和中年人来说,没有太大经济和生活压力,更懂得也有时间享受生活出去旅行。

性别

# 性别分布
payuser_sex = payuser_profile[[\'user_id\', \'sex\']].groupby(\'sex\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
print(payuser_sex)
sex num
1 962
2 27540
3 43487
# 画饼图
plt.pie(payuser_sex[\'num\'], labels=payuser_sex[\'sex\'], autopct=\'%1.2f%%\')
plt.title(\'支付用户按性别分布\')
plt.legend(loc=\'best\')
plt.show()

\"飞猪平台用户行为分析—python_第20张图片\"
1:未知,2:男性,3:女性

支付用户中女性是男性的1.5倍左右,说明现代女性更加独立自主,更喜欢享受生活喜欢旅行,男性经济方面压力大些,相对来说出行欲望较低。

职业

# 职业分布
payuser_career = payuser_profile.groupby(\'career\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
payuser_career[\'percent\'] = payuser_career[\'num\']/payuser_career[\'num\'].sum()

\"飞猪平台用户行为分析—python_第21张图片\"
支付用户的职业主要集中在职业3上,说明这个职业的人比较喜欢出行,也有可能是职业原因(需要出差等~)。

城市

# 城市分布
payuser_city = payuser_profile.groupby(\'use_city_id\')[\'user_id\'].apply(lambda x: x.drop_duplicates().count()).reset_index().rename(columns={\'user_id\': \'num\'})
payuser_city[\'percent\'] = payuser_city[\'num\']/payuser_city[\'num\'].sum()
payuser_city = payuser_city[payuser_city[\'percent\']>0.1]
print(payuser_city)
use_city_id num percent
224 8649 0.12

支付用户占比大于10%的城市只有一个:城市224,可能这个城市比较发达,人民相对富裕,除生活开销外,愿意负担出行的费用享受生活。

3.2.2行为维度

3.2.2.1复购率和跳失率

复购率=购买次数>1的用户/所有购买用户

# 统计每个用户支付次数
pay_times = pay_data[[\'user_id\', \'behavior_type\']].groupby(\'user_id\').agg(\'count\').reset_index().rename(columns={\'behavior_type\': \'paycount\'})
print(pay_times.head())
# 统计支付次数大于1的用户
repay_data = pay_times[pay_times[\'paycount\'] > 1]
user_id paycount
32 6
105 1
257 4
323 1
441 1

复购率=2/5=40%
只购买一次的用户占购买用户总数的60%,有复购行为的人占40%,可以发现高复购次数的人占比较少,商家可以从商品质量、服务制度、物流体验、以及售后服务几个方面寻找原因,找到提高复购率的突破点。

跳失率=点击次数为1的用户/所有点击用户

# 统计每个用户的点击次数
clk_times = pay_data[[\'user_id\', \'behavior_type\']].groupby(\'user_id\').agg(\'count\').reset_index().rename(columns={\'behavior_type\': \'clkcount\'})
# 统计点击次数为1的用户
clk_onetime = clk_times[clk_times[\'clkcount\'] == 1]
# 计算跳失率
bounce_rate = round(clk_onetime.shape[0]/clk_times.shape[0], 2)
print(\'跳失率:\', bounce_rate)

跳失率:47%

复购率偏低,且跳失率较高,说明平台对用户没有足够的吸引力让用户停留。

3.2.2.2漏斗分析

用户从点击到最终支付的过程当中流失率(或转化率)状况

# 总体
pv_total = len(df)
clk_num = len(clk_data) # 点击总计
fav_num = len(fav_data) # 收藏总计
cart_num = len(cart_data) # 加购总计
pay_num = len(pay_data) # 支付总计
pv_total clk_num fav_num cart_num pay_num
7983450 7229031 229732 300665 224022
# 总体各个阶段的流失率计算
Wastage_rate1 = round(1-clk_num/pv_total,4)
Wastage_rate2 = round(1-cart_num/clk_num,4)
Wastage_rate3 = round(1-fav_num/cart_num,4)
Wastage_rate4 = round(1-pay_num/fav_num,3)

\"飞猪平台用户行为分析—python_第22张图片\"
浏览—点击—加购—收藏—购买
总浏览到点击的流失率小说明转化率高,点击到加购流失率太高说明点击转化率低,用户进行点击行为后就没有后续了,收藏到购买的流失率很小,说明用户对这两个用户行为差不多,对于收藏的商品购买的可能性很大。

# 漏斗图--matplotlib

import seaborn as sns
from matplotlib.patches import Polygon  # Polygon()可以用来传入按顺序组织的多边形顶点,从而生成出多边形
from matplotlib.collections import PatchCollection

plt.style.use(\'seaborn-dark\')  # 设置主题
plt.rcParams[\'font.sans-serif\'] = [\'SimHei\']  # 用来正常显示中文标签
plt.rcParams[\'axes.unicode_minus\'] = False  # 用来正常显示负号

data = [clk_num, cart_num, fav_num, pay_num]
phase = [\'点击次数\', \'加购次数\', \'收藏次数\', \'购买次数\']
data1 = [clk_num/2 - i/2 for i in data] # 用来覆盖柱形图左边
data2 = [i+j for i,j in zip(data, data1)] # 柱形图长度=data+覆盖柱形图长度
color_list = [ \'#00685A\', \'#1E786C\',\'#00A08A\',\'#34D0BA\']  # 柱子颜色

fig,ax = plt.subplots(figsize=(16, 9),facecolor=\'#f4f4f4\')
ax.set_title(\'用户转化漏斗图\',fontsize=18)
ax.barh(phase[::-1], data2[::-1], color = color_list, height=0.7)  # 柱宽设置为0.7
ax.barh(phase[::-1], data1[::-1], color = \'#f4f4f4\', height=0.7)  # 设置成背景同色,覆盖柱形图
ax.axis(\'off\')

polygons = []
for i in range(len(data)):
    # 阶段
    ax.text(
        0,  # 坐标
        i,  # 高度
        phase[::-1][i],  # 文本,phase[::-1]表示将列表倒序排列
        color=\'black\', alpha=0.8, size=16, ha=\"right\")

    # 数量
    if i < 3:
        ax.text(
            data2[0] / 2,
            i,
            str(data[::-1][i]) + \'(\' + str(round(data[::-1][i] / data[::-1][i+1] * 100, 1)) + \'%)\',
            color=\'black\', alpha=0.8, size=14, ha=\"center\")
    else:
        ax.text(
            data2[0] / 2,
            i,
            str(data[::-1][i]),
            color=\'black\', alpha=0.8, size=14, ha=\"center\")

    if i < 3:
        # 绘制过渡多边形
        polygons.append(Polygon(xy=np.array([(data1[i + 1], 2 + 0.35 - i),  # 因为柱状图的宽度设置成了0.7,所以一半便是0.35
                                             (data2[i + 1], 2 + 0.35 - i),
                                             (data2[i], 3 - 0.35 - i),
                                             (data1[i], 3 - 0.35 - i)])))

# 使用add_collection与PatchCollection来向Axes上添加多边形
ax.add_collection(PatchCollection(polygons,
                                  facecolor=\'#F56E8D\',
                                  alpha=0.8));

plt.show()

\"飞猪平台用户行为分析—python_第23张图片\"
时间

# 建漏斗函数
def cal_funnel(data, datetime):
    data1 = data.groupby([datetime, \'behavior_type\']).user_id.count().reset_index().rename(columns={\'user_id\': \'total\'})
    # 不一样时间中,各用户行为的用户数量
    lose_rates = [] #流失率
    date2 = pd.Series(data1[datetime].unique())
    for i in date2:
        data2 = data1[data1[datetime] == i]
        clk_to_cart = 1 - data2[data2.behavior_type == 3].reset_index().loc[0, \'total\']/data2[data2.behavior_type == 1].reset_index().loc[0,\'total\']
        cart_to_fav = 1-data2[data2.behavior_type == 2].reset_index().loc[0,\'total\']/data2[data2.behavior_type == 3].reset_index().loc[0,\'total\']
        fav_to_pay = 1-data2[data2.behavior_type == 4].reset_index().loc[0,\'total\']/data2[data2.behavior_type == 2].reset_index().loc[0,\'total\']
        lose_rate = [clk_to_cart, cart_to_fav, fav_to_pay]
        lose_rates.append(lose_rate)
    data3 = pd.DataFrame(lose_rates, index=date2, columns=[\'clk_to_cart\', \'cart_to_fav\', \'fav_to_pay\'])
    return data3

# 按日计算
a_day_lose=cal_funnel(df,\'date\')
# 创建图形
plt.figure(figsize=(20,8), dpi=80)
plt.plot(a_day_lose.index, a_day_lose.clk_to_cart, label=\'点击——加购\')
plt.plot(a_day_lose.index, a_day_lose.cart_to_fav, label=\'加购——收藏\')
plt.plot(a_day_lose.index, a_day_lose.fav_to_pay, label=\'收藏——购买\')

# 添加水平线
plt.axhline(y=0,ls=\"--\",c=\"k\", linewidth=1)

# 添加标注
plt.xlabel(\'日期\',size=15)
plt.ylabel(\'转化率\',size=15)

#添加标题
plt.title(\'用户行为转化流失率\',size=15)

# 添加图例
plt.legend(loc=\'best\')

# 显示折线图
plt.show()

\"飞猪平台用户行为分析—python_第24张图片\"
由上图可以看出,部分日期的收藏—购买流失率处于负值区域,说明该天的成交量大于收藏量,说明成交量只有一小部分来源于收藏,所以不再适用于这种转化路径。

点击—收藏/加购—购买

# 建漏斗函数
def cal_funnel(data, datetime):
    data1 = data.groupby([datetime, \'behavior_type\']).user_id.count().reset_index().rename(columns={\'user_id\': \'total\'})
    # 不一样时间中,各用户行为的用户数量
    lose_rates = [] #流失率
    date2 = pd.Series(data1[datetime].unique())
    for i in date2:
        data2 = data1[data1[datetime] == i] 
        clk_to_favAndcart = 1 - (data2[data2.behavior_type == 2].reset_index().loc[0,\'total\'] + data2[data2.behavior_type == 3].reset_index().loc[0,\'total\'])/data2[data2.behavior_type == 1].reset_index().loc[0,\'total\']
        favAndcart_to_pay = 1-data2[data2.behavior_type == 4].reset_index().loc[0,\'total\']/(data2[data2.behavior_type == 2].reset_index().loc[0,\'total\']+data2[data2.behavior_type == 3].reset_index().loc[0,\'total\'])
        lose_rate = [clk_to_favAndcart, favAndcart_to_pay]
        lose_rates.append(lose_rate)
    data3 = pd.DataFrame(lose_rates, index=date2, columns=[\'clk_to_favAndcart\', \'favAndcart_to_pay\'])
    return data3

# 按日计算
a_day_lose2=cal_funnel(df,\'date\')
# 创建图形
plt.figure(figsize=(20,8), dpi=80)
plt.plot(a_day_lose2.index, a_day_lose2.clk_to_favAndcart, label=\'点击——收藏/加购\')
plt.plot(a_day_lose2.index, a_day_lose2.favAndcart_to_pay, label=\'收藏/加购——购买\')

# 添加水平线
plt.axhline(y=0.5, ls=\"--\",c=\"k\", linewidth=1)

# 添加标注
plt.xlabel(\'日期\',size=15)
plt.ylabel(\'转化率\',size=15)

#添加标题
plt.title(\'用户行为转化流失率\',size=15)

# 添加图例
plt.legend(loc=\'best\')

# 显示折线图
plt.show()

\"飞猪平台用户行为分析—python_第25张图片\"
在该月份期间,用户的点击—收藏/加购流失率一直居高不下,转化率极低,收藏/加购—购买的流失率大部分时间都大于50%,只有在月初的时候较低。

3.2.2.3用户行为在时间上的分布

# 按日分布
clk_date = clk_data[[\'user_id\', \'date\']].groupby(\'date\')[\'user_id\'].agg(\'count\')
cart_date = cart_data[[\'user_id\', \'date\']].groupby(\'date\')[\'user_id\'].agg(\'count\')
fav_date = fav_data[[\'user_id\', \'date\']].groupby(\'date\')[\'user_id\'].agg(\'count\')
pay_date = pay_data[[\'user_id\', \'date\']].groupby(\'date\')[\'user_id\'].agg(\'count\')

# 按时分布
clk_hour = clk_data[[\'user_id\', \'hour\']].groupby(\'hour\')[\'user_id\'].agg(\'count\')
cart_hour = cart_data[[\'user_id\', \'hour\']].groupby(\'hour\')[\'user_id\'].agg(\'count\')
fav_hour = fav_data[[\'user_id\', \'hour\']].groupby(\'hour\')[\'user_id\'].agg(\'count\')
pay_hour = pay_data[[\'user_id\', \'hour\']].groupby(\'hour\')[\'user_id\'].agg(\'count\')

# 按周分布
clk_weekday = clk_data[[\'user_id\', \'weekday\']].groupby(\'weekday\')[\'user_id\'].agg(\'count\')
cart_weekday = cart_data[[\'user_id\', \'weekday\']].groupby(\'weekday\')[\'user_id\'].agg(\'count\')
fav_weekday = fav_data[[\'user_id\', \'weekday\']].groupby(\'weekday\')[\'user_id\'].agg(\'count\')
pay_weekday = pay_data[[\'user_id\', \'weekday\']].groupby(\'weekday\')[\'user_id\'].agg(\'count\')
# 创建图形
fig = plt.figure(figsize=(20,10),dpi=80)
plt.grid(True, linestyle=\"--\", alpha=0.5)
plt.xticks([])  #去掉横坐标值
plt.yticks([])  #去掉纵坐标值

ax1 = fig.add_subplot(311)
date = clk_date.index.tolist()
ax1.bar(date, clk_date.values, label=\'每日用户点击量\')
ax1.set_ylabel(\'数量\')
ax1.set_title(\'用户行为按天分布\', size=10)
ax1.legend(loc=\'upper left\')
ax2 = ax1.twinx() 
ax2.plot(date, cart_date.values, \'r\', label=\'每日用户加购量\', linewidth=2)
ax2.plot(date, fav_date.values, \'k\', label=\'每日用户收藏量\', linewidth=2)
ax2.plot(date, pay_date.values, \'y\', label=\'每日用户购买量\', linewidth=2)
ax2.set_ylabel(\'数量\')
ax2.set_xlabel(\'日期\')
ax2.legend(loc=\'upper right\')

ax1 = fig.add_subplot(312)
hour = clk_hour.index.tolist()
ax1.bar(hour, clk_hour.values, label=\'每小时用户点击量\')
ax1.set_ylabel(\'数量\')
ax1.set_title(\'用户行为按时刻分布\', size=10)
ax1.legend(loc=\'upper left\')
ax2 = ax1.twinx() 
ax2.plot(hour, cart_hour.values, \'r\', label=\'每日用户加购量\', linewidth=2)
ax2.plot(hour, fav_hour.values, \'k\', label=\'每日用户收藏量\', linewidth=2)
ax2.plot(hour, pay_hour.values, \'y\', label=\'每日用户购买量\', linewidth=2)
ax2.set_ylabel(\'数量\')
ax2.set_xlabel(\'时刻\')
ax2.legend(loc=\'upper right\')

ax1 = fig.add_subplot(313)
weekday = clk_weekday.index.tolist()
length = len(clk_weekday)
x = np.arange(length) # 横坐标 
total_width, n = 0.6, 3 # 柱状总宽度,数据组数
width = total_width / n # 每个柱状的宽度
x1 = x - width / 3 # 第一组柱状横坐标起始位置
x2 = x1 + width # 第二组柱状横坐标起始位置
x3 = x2 + width  # 第三组柱状横坐标起始位置
ax1.plot(weekday, clk_weekday.values, \'r\', linewidth=1, label=\'每周几用户点击量\')
ax1.set_ylabel(\'数量\')
ax1.set_title(\'用户行为按星期分布\', size=10)
ax1.legend(loc=\'upper left\')
ax2 = ax1.twinx() 
ax2.bar(x1, cart_weekday.values, width=width, label=\'每周几用户加购量\')
ax2.bar(x2, fav_weekday.values, width=width, label=\'每周几用户收藏量\')
ax2.bar(x3, pay_weekday.values, width=width, label=\'每周几用户购买量\')
ax2.set_xticks(x, weekday)
ax2.set_ylabel(\'数量\')
ax2.set_xlabel(\'星期\')
ax2.legend(loc=\'upper right\')

plt.show()

\"飞猪平台用户行为分析—python_第26张图片\"

  • 用户点击量在月初最高,随着时间的推移不断降低直至平缓,收藏、加购、购买在5月底拐点一致,达到最高;
  • 用户在傍晚活跃度最低,喜欢在凌晨支付,尤其是凌晨2点,其余时刻用户点击和加购的变化一致,收藏和购买的变化一致;
  • 用户在周一最活跃,点击、收藏、加购、购买同时达到最大值,购买路径转化率最高。

3.3 商品分析

3.3.1热门商品分析

# 读取数据\'item_profile.csv\'
item_profile = pd.read_csv(\'./data/item_profile.csv\', header=None, names = [\'item_id\',\'item_category_id\',\'item_city\',\'item_label\'], encoding=\'utf8\')
print(item_profile.head())

\"飞猪平台用户行为分析—python_第27张图片\"

# 按商品分组统计商品被点击、加购、收藏、购买的数量
item_clk_num = clk_data.groupby(\'item_id\')[\'behavior_type\'].count().reset_index().rename(columns={\'behavior_type\':\'clk_num\'})
item_cart_num = cart_data.groupby(\'item_id\')[\'behavior_type\'].count().reset_index().rename(columns={\'behavior_type\':\'cart_num\'})
item_fav_num = fav_data.groupby(\'item_id\')[\'behavior_type\'].count().reset_index().rename(columns={\'behavior_type\':\'fav_num\'})
item_pay_num = pay_data.groupby(\'item_id\')[\'behavior_type\'].count().reset_index().rename(columns={\'behavior_type\':\'pay_num\'})
# 商品点击Top10
item_clk_num = item_clk_num.sort_values(by=\'clk_num\', ascending=False)
item_clk_Top10 = item_clk_num.head(10)

# 商品收藏+加购Top10
favcart_data = pd.concat([fav_data, cart_data], axis=0)
item_favcart_num = favcart_data.groupby(\'item_id\')[\'behavior_type\'].count().reset_index().rename(columns={\'behavior_type\':\'favcart_num\'})
item_favcart_num = item_favcart_num.sort_values(by=\'favcart_num\', ascending=False)
item_favcart_Top10 = item_favcart_num.head(10)

# 商品购买Top10
item_pay_num = item_pay_num.sort_values(by=\'pay_num\', ascending=False)
item_pay_Top10 = item_pay_num.head(10)

3.3.2购买路径分析

1.点击——购买:ctop_rate; 2.收藏/加购——购买:ftop_rate;

# Top10转化率

df1 = item_clk_Top10.merge(item_pay_Top10, on=\'item_id\').merge(item_favcart_Top10, on=\'item_id\')
# 点击——购买
df1[\'ctop_rate\'] = round(df1[\'pay_num\']/df1[\'clk_num\'],4)
# 收藏/加购——购买
df1[\'fctop_rate\'] = round(df1[\'pay_num\']/df1[\'favcart_num\'],4)
print(df1)
# 平均转化率
ctop_avg_rate = round(df1[\'pay_num\'].sum()/df1[\'clk_num\'].sum(),2)
fctop_avg_rate = round(df1[\'pay_num\'].sum()/df1[\'favcart_num\'].sum(),2)
# matplotlib可视化

import matplotlib.ticker as ticker

fig = plt.figure(figsize=(8,5),dpi=80)
colors = [\'#CC9999\',\'#FFFF99\',\'#666699\']
x = tuple(df1[\'item_id\'].apply(str)) #list transform to tuple
print(x)

# 点击-购买转化率
ax1 = fig.add_subplot(211)
ax1.set_title(\'点击Top10商品购买转化率\',fontsize=14)
ax1.bar(x,df1.clk_num,width=0.3,color=colors) # 柱状图显示点击量
ax1.set_xlabel(\'商品ID\', size = 10)
ax1.set_ylabel(\'点击量\', size = 10)

ax2 = ax1.twinx()
ax2.plot(x,df1.ctop_rate)
ax2.set_ylabel(\'点击-购买转化率\', size = 10) 
ax2.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))
ax2.axhline(y=ctop_avg_rate,c=\'r\',ls=\':\',label=\'平均购买转换率\') #添加水平直线

# 收藏-购买转化率
ax3 = fig.add_subplot(212)
ax3.set_title(\'收藏/加购Top10商品购买转化率\',fontsize=14)
ax3.bar(x,df1.favcart_num,color=colors,width=0.3) 

ax3.set_xlabel(\'商品ID\', size = 10)
ax3.set_ylabel(\'收藏加购量\', size = 10)

ax4 = ax3.twinx()
ax4.axhline(y=fctop_avg_rate,c=\'r\',ls=\':\',label=\'平均购买转换率\') #添加水平直线
ax4.plot(scale_ls,df1.fctop_rate)
ax4.set_ylabel(\'收藏/加购-购买转化率\', size = 10)
ax4.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=1))

plt.tight_layout()   # 自动调整各子图间距

plt.show()

\"飞猪平台用户行为分析—python_第28张图片\"通过可视化分析,点击量、收藏加购量高的商品,购买转化率不一定高,相关性不成正比,尤其是收藏加购量最高的商品购买转化率反而是最低的,可以这类商品增加关注。

3.3.3商品画像

# item_pay_Top10根据item_id拼接item_profile
payitem_profile = pd.merge(item_pay_Top10, item_profile, how=\'left\', on=\'item_id\')

item_category_num = payitem_profile.groupby(\'item_category_id\')[\'pay_num\'].sum().reset_index().rename(columns={\'pay_num\':\'pay_sum\'})
item_city_num = payitem_profile.groupby(\'item_city\')[\'pay_num\'].sum().reset_index().rename(columns={\'pay_num\':\'pay_sum\'})
item_label_num = payitem_profile.groupby(\'item_label\')[\'pay_num\'].sum().reset_index().rename(columns={\'pay_num\':\'pay_sum\'})
# matplotlib可视化

fig = plt.figure(figsize=(9,5),dpi=80)

# 购买商品Top10种类分布
ax1 = fig.add_subplot(311)
ax1.set_title(\'购买商品Top10种类分布\',fontsize=14)
x1 = tuple(item_category_num[\'item_category_id\'].apply(str))
y1 = item_category_num[\'pay_sum\']
colors1 = [\'#CC9999\',\'#FFFF99\',\'#666699\']
ax1.barh(x1,y1,color=colors1)
ax1.set_xlabel(\'商品种类\', size = 10)
ax1.set_ylabel(\'成交量\', size = 10)

# 购买商品Top10区域分布
ax1 = fig.add_subplot(312)
ax1.set_title(\'购买商品Top10区域分布\',fontsize=14)
x1 = tuple(item_city_num[\'item_city\'].apply(str))
y1 = item_city_num[\'pay_sum\']
colors2 = [\'#FF9900\',\'#009999\',\'#CCCC99\', \'#CC3399\']
ax1.barh(x1,y1,color=colors2)
ax1.set_xlabel(\'城市\', size = 10)
ax1.set_ylabel(\'成交量\', size = 10)

# 购买商品Top10标签分布
ax1 = fig.add_subplot(313)
ax1.set_title(\'购买商品Top10标签分布\',fontsize=14)
x1 = tuple(item_label_num[\'item_label\'].apply(str))
y1 = item_label_num[\'pay_sum\']
colors3 = [\'#FF6666\',\'#0099CC\',\'#009966\']
ax1.barh(x1,y1,color=colors3)
ax1.set_xlabel(\'商品标签\', size = 10)
ax1.set_ylabel(\'成交量\', size = 10)

plt.tight_layout()   # 自动调整各子图间距

plt.show()

\"飞猪平台用户行为分析—python_第29张图片\"
购买商品Top10的种类主要集中在ID为4、13、30的种类;
购买商品Top10 的城市主要分布在ID为224、248、383、561的城市;
购买商品Top10 的标签主要是ID为-1、169、94的标签。


五、总结

  1. 从总体上看,用户的活跃度和转化率都比较低,可能跟产品性质有关,一般使用频率不高,只有有需求时才会产生用户行为;
  2. 用户在凌晨三点成交率最高,在晚上8点最低,周日不活跃成交率低;是否有活动优惠对用户行为影响较大,会提前选好自己感兴趣的商品,直到活动将近结束时才会决定购买;
  3. 支付用户的年龄主要集中在45~60岁年龄段,这个年龄的用户在退休年龄左右,没有太大经济和生活压力,也有时间享受生活;支付用户的职业主要是ID为3,这个可能跟职业性质有关;支付用户中女性远大于男性,说明现在的女性更独立自主喜欢出行,更懂得享受生活,而男性可能经济压力较大,出行欲望较低;
  4. 用户的复购率很低,低于50%,跳失率很高,将近50%,留存率整体很低,说明用户粘度不高,平台对用户的吸引力很低,商家可以从页面设计、精准推送、服务制度以及售后服务几个方面寻找原因;
  5. 用户点击到加购的流失率太高,说明商品对用户的吸引度不够,收藏到购买的流失率极低,说明用户收藏商品的购买可能性极高,但收藏量较低,用户转化率问题比较大,整体太低,需要根据用户需求针对性的改善平台及其商品;
  6. 在商品Top10分析中,可以看出高点击量、收藏加购量的商品,购买量不一定最高,购买商品的种类和标签具有集中性,可以对这类商品提高关注度,提高转化率;
  7. 由于本项目的数据样本只有一个月,导致时间维度特征不够复杂,所以对于有些指标的分析具有局限性,如果有多个月份数据按月份维度分析会更好,结果也更具参考意义。

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号