【数据分析案例】基于Pandas分析天池大赛项目 - 淘宝用户行为数据推荐

前言:

        经典网红数分项目,本文利用pandas处理数据,不实现数据可视化图表,读者可自行根据数据分析出来的结果或自身分析思路做一个数据分析总结


原文摘要:

        本数据集包含了 2017 年 11 月 25 日 2017 年 12 月 3 日之间,有行为的约一百万随机用户的所有行为(行为包括点击、购买、加购、喜欢)。

        数据集的每一行表示一条用户行为,由用户 ID、商品 ID、商品类目 ID、行为类型和时间戳组成,并以逗号分隔。


关于数据集的详细描述如下:

数据源链接:数据集-阿里云天池

数据特征:

User_id(用户ID):整数类型

item_id(商品ID):整数类型

cate_id(类目ID):整数类型

act_id(行为类型):字符串,枚举类型

        包含‘pv’(点击)、‘buy’(购买),‘cart’(加购),‘fav’(收藏)

time(时间戳):行为发生的时间戳


分析思路:

  1. 基础设置(导入模块、格式设置、数据整体预览)
  2. 数据清洗(查重、缺失值、异常值)
  3. 数据整体情况分析(UV、PV、人均浏览、成交量)
  4. 用户行为(时间、产品、转化链路维度)
  5. 用户分层(只有R和F)
  6. 用户复购(复购率、复购类目和商品)
  7. 用户收藏与购买的相关性

基础设置

导入数据

import pandas as pd
import time
start_time = time.time()

# 数据源
path = r'C:\Users\x\Desktop\UserBehavior.csv\UserBehavior.csv'   # 文件地址
columns_name = ['user_id', 'product_id', 'tag', 'act_id', 'time']   # 列名
data = pd.read_csv(path, header=None, names=columns_name)   # 导入数据

观察数据规模,展现形式

print(data.shape)
print(data.isnull().sum())
print(data.describe)
print(data.info)

数据清洗

对特定字段进行格式转化

转化时间戳格式,并增加日期、星期、小时字段

# 数据格式调整
data['time'] = pd.to_datetime(data['time'], unit='s')
data['date'] = pd.to_datetime(data['time'].dt.date)
data['weekday'] = data['time'].dt.weekday
data['hour'] = data['time'].dt.hour

查重、缺失值处理

可以看到,没有缺失或重复的数据

print('行重复数:', data.duplicated().sum())
print('各指标缺失值:', '\n', data.isnull().sum())
print('\n','-' * 100,'\n')

异常值处理

因为数据仅处于2017年11月25日至2017年12月3日之间,数据范围外均为异常数据,按异常数据丢弃处理

data = data[(data['date'] > "2017-11-24" ) & (data['date'] < "2017-12-04") ]

数据整体情况分析

各指标去重数量:

user_id: 共 987984 个

product_id: 共 4142583 个

tag: 共 9435 个

act_id: 共 4 个

其中,行为的指标分别为:['pv' 'buy' 'fav' 'cart']

# 数据总体了解
print('各指标去重数量:')
for i in list(data.columns.values)[:4]: #前四个为原先定义的指标
    print('{}: 共 {} 个'.format(i, data[i].nunique()))
act_id_list = data['act_id'].unique()   # 获取行为的分类
print('其中,行为的指标分别为:{}'.format(act_id_list))
print('\n','-' * 100,'\n')

访问人数 = 987984

uv_cnt = data['user_id'].nunique()

访问频次 = 88596903

pv_cnt = data[data['act_id'] == 'pv'].act_id.count()

平均访问量 = 89.67%

avg_pv = print('平均访问量:{}'.format(round(pv_cnt / uv_cnt,2)))

购买次数 = 1998976

buy_cnt = data[data['act_id'] == 'buy'].act_id.count()

购买人数 = 670370

buy_per_cnt = data[data['act_id'] == 'buy'].user_id.nunique()

购买人数占比 = 68%

print('平均访问量:{} %'.format(round(buy_per_cnt / uv_cnt * 100)))

人均购买次数 = 2.98

print('人均购买次数:{}'.format(round(buy_cnt / buy_per_cnt,2)))

转化率

商品点加率:6%

商品点藏率:3%

商品点购率:2%

print('商品点加率:{} %'.format(round(data[data['act_id'] == 'cart'].act_id.count() / pv_cnt* 100)))
print('商品点藏率:{} %'.format(round(data[data['act_id'] == 'fav'].act_id.count() / pv_cnt * 100)))
print('商品点购率:{} %'.format(round(data[data['act_id'] == 'buy'].act_id.count() / pv_cnt * 100)))

TOP

print('购买频数前五名商品:', '\n', data['product_id'].value_counts().head(), '\n')
print('购买频数前五名商品类目:', '\n', data['tag'].value_counts().head(), '\n')


用户行为分析

时间维度

按日期统计访问次数

date = data[data['act_id'] == 'pv'].groupby(by='date').agg(pv=('user_id','count'))

按星期统计购买次数

weekday = data[data['act_id'] == 'buy'].groupby(by='weekday').agg(pv=('user_id','count'))

按小时统计访问次数和购买次数

hour_pv_cnt = data[data['act_id'] == 'pv'].groupby(by='hour').agg(pv_cnt=('user_id','count'))
hour_buy_cnt = data[data['act_id'] == 'buy'].groupby(by='hour').agg(buy_cnt=('user_id','count'))
hour = pd.concat([hour_pv_cnt,hour_buy_cnt],axis=1)

产品维度

热门类目和热卖类目

pv_tag_top = data[data['act_id'] == 'pv'].groupby('tag').agg(pv_tag=('user_id','count')).sort_values('pv_tag',ascending=False)
print('访问频数前五名商品类目:', '\n', pv_tag_top.head(), '\n')
buy_tag_top = data[data['act_id'] == 'buy'].groupby('tag').agg(buy_tag=('act_id','count')).sort_values('buy_tag',ascending=False)
print('购买频数前五名商品类目:', '\n', buy_tag_top.head(), '\n')
pv_and_buy_top = pd.concat([pv_tag_top,buy_tag_top],axis=1,join='inner').sort_values('buy_tag',ascending=False)
print('访问且购买频数前五名商品类目:', '\n', pv_and_buy_top.head(), '\n')

热门商品和热卖商品

pv_product_top = data[data['act_id'] == 'pv'].groupby('product_id').agg(pv_product=('user_id','count')).sort_values('pv_product',ascending=False)
print('访问频数前五名商品:', '\n', pv_product_top.head(), '\n')
buy_product_top = data[data['act_id'] == 'buy'].groupby('product_id').agg(buy_product=('user_id','count')).sort_values('buy_product',ascending=False)
print('购买频数前五名商品:', '\n', buy_product_top.head(), '\n')
pv_and_buy_top = pd.concat([pv_product_top,buy_product_top],axis=1,join='inner').sort_values('buy_product',ascending=False)
print('访问且购买频数前五名商品:', '\n', pv_and_buy_top.head(), '\n')

转化链路

用户行为路径我分为了两种:

用户行为路径一:pv-cart-buy

        用户行为路径p-c-b的转化率为: p-c:16.21%, c-b:2.73%

用户行为路径二:pv-fav-cart-buy

        用户行为路径p-f-c-b的转化率为: p-f:31.06%, f-c:0.52%, c-b:2.73%

# 行为路径一:p-c-b
pc = round(data[data['act_id'] == 'pv'].act_id.count() / data[data['act_id'] == 'cart'].act_id.count() , 2)
cb = round(data[data['act_id'] == 'cart'].act_id.count()  / data[data['act_id'] == 'buy'].act_id.count() , 2)
print('用户行为路径p-c-b的转化率为:', 'p-c:{}%, c-b:{}%'.format(pc, cb))
# 行为路径二:p-f-c-b
pf = round(data[data['act_id'] == 'pv'].act_id.count() / data[data['act_id'] == 'fav'].act_id.count(), 2)
fc = round(data[data['act_id'] == 'fav'].act_id.count() / data[data['act_id'] == 'cart'].act_id.count(), 2)
cb = round(data[data['act_id'] == 'cart'].act_id.count() / data[data['act_id'] == 'buy'].act_id.count(), 2)
print('用户行为路径p-f-c-b的转化率为:', 'p-f:{}%, f-c:{}%, c-b:{}%'.format(pf, fc, cb))

十分明显可以看到,点击数与其他行为数量差距过大


用户价值分层

RFM用户价值模型,主要有三个核心指标,用户唯一ID,最近一次购买时间,购买金额

因为数据不涉及到金额方面,默认都为金额高的用户,因此,仅分析R和F两个层面,并对用户进行四个层次的分级

# FRM用户价值分层模型
RFM = data[data['act_id'] == 'buy'].groupby('user_id',as_index=False).agg({'act_id':'count','date':'max'})
RFM['R'] = (pd.to_datetime('2017-12-03')-RFM['date']).dt.days
RFM.rename(columns={'act_id':'F'},inplace=True)
RFM.drop(columns=['date'],inplace=True)

# 方式一:等距分箱的形式划分
RFM['R_label1'] = pd.cut(RFM['R'],bins=2,right=False,labels=range(0,2)).astype('int')
RFM['F_label1'] = pd.cut(RFM['F'],bins=2,right=False,labels=range(0,2)).astype('int')

# 方式二:按平均分的形式划分
# RFM['R_label2'] = (RFM['R'] >= RFM['R'].mean()) * 1
# RFM['F_label2'] = (RFM['F'] >= RFM['F'].mean()) * 1

# 用户分层
for i,j in RFM.iterrows():
    if j['R_label1'] == 1 and j['F_label1'] == 1:
        RFM.loc[i,'用户类别'] = '价值用户'
    if j['R_label1'] == 1 and j['F_label1'] == 0:
        RFM.loc[i,'用户类别'] = '发展用户'
    if j['R_label1'] == 0 and j['F_label1'] == 1:
        RFM.loc[i,'用户类别'] = '保持用户'
    if j['R_label1'] == 0 and j['F_label1'] == 0:
        RFM.loc[i,'用户类别'] = '挽留用户'

可以可视化观察对比下每个层级的用户数和占比或者细化商品类目观察其分层情况

用户复购

复购率 = 66%

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

repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_rate = round(repurchase[repurchase['act_id'] > 1]['act_id'].count()/ repurchase['act_id'].count(),2)*100
print('复购率:{} %'.format(re_rate))

最热卖复购类目(对比热卖类目)

repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_tag_top = data[data['user_id'].isin(repurchase[repurchase['act_id'] >1]['user_id'])].reset_index()
re_tag_top = re_tag_top[re_tag_top['act_id'] == 'buy'].groupby('tag').agg(re_tag=('act_id','count')).sort_values('re_tag',ascending=False).head()
contrast_tag = pd.concat([buy_tag_top,re_tag_top],axis=1,join='inner')

最热卖复购商品(对比热卖商品)

repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_product_top = data[data['user_id'].isin(repurchase[repurchase['act_id'] >1]['user_id'])].reset_index()
re_product_top = re_product_top[re_product_top['act_id'] == 'buy'].groupby('product_id').agg(re_product=('act_id','count')).sort_values('re_product',ascending=False).head()
contrast_product = pd.concat([buy_product_top,re_product_top],axis=1,join='inner')

用户收藏与购买的相关性

皮尔逊相关系数 = 0.18

corr_cart = data[data['act_id'] == 'cart'].groupby('user_id').agg(cart=('act_id','count'))
corr_buy = data[data['act_id'] == 'buy'].groupby('user_id').agg(buy=('act_id','count'))
corr_data = pd.concat([corr_cart,corr_buy],axis=1).fillna(0)
corr = round(corr_data['cart'].corr(corr_data['buy'])*100,2)

完整代码

方便读者完善代码思路,奉上完整的代码,以供参考,建议以自己的分析思路用pandas实现数据处理

运行该代码时,请注意修改文件地址

# !/usr/bin/python3.7
# -*- coding:utf-8 -*-
# @author:inganxu
# CSDN:inganxu.blog.csdn.net
# @Date:2023年9月18日
import pandas as pd
import time
start_time = time.time()

# 数据源
path = r'C:\Users\x\Desktop\UserBehavior.csv\UserBehavior.csv'   # 文件地址
columns_name = ['user_id', 'product_id', 'tag', 'act_id', 'time']   # 列名
data = pd.read_csv(path, header=None, names=columns_name)   # 导入数据
data = data.head(100000)

# 数据预处理
# 数据格式调整
data['time'] = pd.to_datetime(data['time'], unit='s')
data['date'] = pd.to_datetime(data['time'].dt.date)
data['weekday'] = data['time'].dt.weekday
data['hour'] = data['time'].dt.hour

# 查重、缺失值处理
print('行重复数:', data.duplicated().sum())
print('各指标缺失值:', '\n', data.isnull().sum())
print('\n','-' * 100,'\n')

# 异常数据处理
# 因为数据仅处于2017年11月25日至2017年12月3日之间,2017-11-24前的数据均为异常数据,按异常数据丢弃处理
data = data[(data['date'] > "2017-11-24" ) & data['date'] < "2017-12-04" ]

# 数据总体了解
print('各指标去重数量:')
for i in list(data.columns.values)[:4]: #前四个为原先定义的指标
    print('{}: 共 {} 个'.format(i, data[i].nunique()))
act_id_list = data['act_id'].unique()   # 获取行为的分类
print('其中,行为的指标分别为:{}'.format(act_id_list))
print('\n','-' * 100,'\n')

# UV
uv_cnt = data['user_id'].nunique()
# PV
pv_cnt = data[data['act_id'] == 'pv'].act_id.count()
# 平均访问量
avg_pv = print('平均访问量:{}'.format(round(pv_cnt / uv_cnt,2)))
# 购买次数
buy_cnt = data[data['act_id'] == 'buy'].act_id.count()
# 购买人数
buy_per_cnt = data[data['act_id'] == 'buy'].user_id.nunique()
# 购买人数占比
print('平均访问量:{} %'.format(round(buy_per_cnt / uv_cnt * 100)))
# 人均购买次数
print('人均购买次数:{}'.format(round(buy_cnt / buy_per_cnt,2)))
# 转化率
print('商品点加率:{} %'.format(round(data[data['act_id'] == 'cart'].act_id.count() / pv_cnt* 100)))
print('商品点藏率:{} %'.format(round(data[data['act_id'] == 'fav'].act_id.count() / pv_cnt * 100)))
print('商品点购率:{} %'.format(round(data[data['act_id'] == 'buy'].act_id.count() / pv_cnt * 100)))
# TOP
print('购买频数前五名商品:', '\n', data['product_id'].value_counts().head(), '\n')
print('购买频数前五名商品类目:', '\n', data['tag'].value_counts().head(), '\n')
print('\n','-' * 100,'\n')

# 用户行为分析
# 时间维度
# 按日期统计访问次数
date = data[data['act_id'] == 'pv'].groupby(by='date').agg(pv=('user_id','count'))

# 按星期统计购买次数
weekday = data[data['act_id'] == 'buy'].groupby(by='weekday').agg(pv=('user_id','count'))

# 按小时统计访问次数和购买次数
hour_pv_cnt = data[data['act_id'] == 'pv'].groupby(by='hour').agg(pv_cnt=('user_id','count'))
hour_buy_cnt = data[data['act_id'] == 'buy'].groupby(by='hour').agg(buy_cnt=('user_id','count'))
hour = pd.concat([hour_pv_cnt,hour_buy_cnt],axis=1)

# 产品维度
# 热门类目和热卖类目
pv_tag_top = data[data['act_id'] == 'pv'].groupby('tag').agg(pv_tag=('user_id','count')).sort_values('pv_tag',ascending=False)
print('访问频数前五名商品类目:', '\n', pv_tag_top.head(), '\n')
buy_tag_top = data[data['act_id'] == 'buy'].groupby('tag').agg(buy_tag=('act_id','count')).sort_values('buy_tag',ascending=False)
print('购买频数前五名商品类目:', '\n', buy_tag_top.head(), '\n')
pv_and_buy_top = pd.concat([pv_tag_top,buy_tag_top],axis=1,join='inner').sort_values('buy_tag',ascending=False)
print('访问且购买频数前五名商品类目:', '\n', pv_and_buy_top.head(), '\n')
# 热门商品和热卖商品
pv_product_top = data[data['act_id'] == 'pv'].groupby('product_id').agg(pv_product=('user_id','count')).sort_values('pv_product',ascending=False)
print('访问频数前五名商品:', '\n', pv_product_top.head(), '\n')
buy_product_top = data[data['act_id'] == 'buy'].groupby('product_id').agg(buy_product=('user_id','count')).sort_values('buy_product',ascending=False)
print('购买频数前五名商品:', '\n', buy_product_top.head(), '\n')
pv_and_buy_top = pd.concat([pv_product_top,buy_product_top],axis=1,join='inner').sort_values('buy_product',ascending=False)
print('访问且购买频数前五名商品:', '\n', pv_and_buy_top.head(), '\n')

# 转化链路
# 行为路径一:p-c-b
pc = round(data[data['act_id'] == 'pv'].act_id.count() / data[data['act_id'] == 'cart'].act_id.count() , 2)
cb = round(data[data['act_id'] == 'cart'].act_id.count()  / data[data['act_id'] == 'buy'].act_id.count() , 2)
print('用户行为路径p-c-b的转化率为:', 'p-c:{}%, c-b:{}%'.format(pc, cb))
# 行为路径二:p-f-c-b
pf = round(data[data['act_id'] == 'pv'].act_id.count() / data[data['act_id'] == 'fav'].act_id.count(), 2)
fc = round(data[data['act_id'] == 'fav'].act_id.count() / data[data['act_id'] == 'cart'].act_id.count(), 2)
cb = round(data[data['act_id'] == 'cart'].act_id.count() / data[data['act_id'] == 'buy'].act_id.count(), 2)
print('用户行为路径p-f-c-b的转化率为:', 'p-f:{}%, f-c:{}%, c-b:{}%'.format(pf, fc, cb))
print('\n','-' * 100,'\n')



# FRM用户价值分层模型
RFM = data[data['act_id'] == 'buy'].groupby('user_id',as_index=False).agg({'act_id':'count','date':'max'})
RFM['R'] = (pd.to_datetime('2017-12-03')-RFM['date']).dt.days
RFM.rename(columns={'act_id':'F'},inplace=True)
RFM.drop(columns=['date'],inplace=True)

# 方式一:等距分箱的形式划分
RFM['R_label1'] = pd.cut(RFM['R'],bins=2,right=False,labels=range(0,2)).astype('int')
RFM['F_label1'] = pd.cut(RFM['F'],bins=2,right=False,labels=range(0,2)).astype('int')

# 方式二:按平均分的形式划分
# RFM['R_label2'] = (RFM['R'] >= RFM['R'].mean()) * 1
# RFM['F_label2'] = (RFM['F'] >= RFM['F'].mean()) * 1

# 用户分层
for i,j in RFM.iterrows():
    if j['R_label1'] == 1 and j['F_label1'] == 1:
        RFM.loc[i,'用户类别'] = '价值用户'
    if j['R_label1'] == 1 and j['F_label1'] == 0:
        RFM.loc[i,'用户类别'] = '发展用户'
    if j['R_label1'] == 0 and j['F_label1'] == 1:
        RFM.loc[i,'用户类别'] = '保持用户'
    if j['R_label1'] == 0 and j['F_label1'] == 0:
        RFM.loc[i,'用户类别'] = '挽留用户'
print(RFM)
print('\n','-' * 100,'\n')



# 用户复购行为
# 复购率 = 购买2次及以上的用户数 / 购买过的总用户数
repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_rate = round(repurchase[repurchase['act_id'] > 1]['act_id'].count()/ repurchase['act_id'].count(),2)*100
print('复购率:{} %'.format(re_rate))
print('\n','-' * 100,'\n')

# 最热卖复购类目(对比热卖类目)
repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_tag_top = data[data['user_id'].isin(repurchase[repurchase['act_id'] >1]['user_id'])].reset_index()
re_tag_top = re_tag_top[re_tag_top['act_id'] == 'buy'].groupby('tag').agg(re_tag=('act_id','count')).sort_values('re_tag',ascending=False).head()
contrast_tag = pd.concat([buy_tag_top,re_tag_top],axis=1,join='inner')
print(contrast_tag)

# 最热卖复购商品(对比热卖商品)
repurchase = data[data['act_id'] == 'buy'].groupby(by='user_id',as_index=False).agg({'act_id':'count'})
re_product_top = data[data['user_id'].isin(repurchase[repurchase['act_id'] >1]['user_id'])].reset_index()
re_product_top = re_product_top[re_product_top['act_id'] == 'buy'].groupby('product_id').agg(re_product=('act_id','count')).sort_values('re_product',ascending=False).head()
contrast_product = pd.concat([buy_product_top,re_product_top],axis=1,join='inner')
print(contrast_product)
print('\n','-' * 100,'\n')


# 计算购买和收藏之间的Pearson相关性
corr_cart = data[data['act_id'] == 'cart'].groupby('user_id').agg(cart=('act_id','count'))
corr_buy = data[data['act_id'] == 'buy'].groupby('user_id').agg(buy=('act_id','count'))
corr_data = pd.concat([corr_cart,corr_buy],axis=1).fillna(0)
corr = round(corr_data['cart'].corr(corr_data['buy'])*100,2)
print('Pearsons correlation:{} %'.format(corr))

end_time = time.time()
print('\n','任务运行时长:', round(end_time - start_time, 2), '秒')


结语:

本文仅对数据作简单的整体分析,没对数据深度分析,感兴趣的读者可根据自身条件针对某个方面进一步分析,例如:

挖掘用户收藏与购买的黄金时间差,并在黄金时间内提供相关促进消费决策。如:发放限时优惠券、增加收藏商品的曝光度...

对比TOP类目或商品在高峰时段(星期、小时)的购买频率是否高于日常

读者也可以针对分析处理后的数据以可视化的形式展现,例如:matplotlibseaborn


参考文章:

淘宝用户行为数据分析_valkyrja110的博客-CSDN博客

基于客观事实的 RFM 模型(Python 代码)_Python_xiaowu的博客-CSDN博客_rfm模型python代码

【matplotlib】浅谈python图形可视化练习经验分享_inganxu的博客-CSDN博客

【数据分析案例】pandas + matplotlib 人货场+RFM+用户复购分析 电商水果销售_inganxu的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

inganxu

感谢您的支持!!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值