美文网首页
某店铺双12前后消费行为分析

某店铺双12前后消费行为分析

作者: shimo_chang | 来源:发表于2020-07-23 11:37 被阅读0次

1、导入所需要的库

numpy、pandas、matplotlib、seaborn和pyecharts

设置中文显示问题


import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from datetime import datetime
from pyecharts.charts import Funnel


sns.set(style = 'darkgrid',font_scale = 1.5)       # 设置sns的风格为darkgrid,曲线宽度为1.5

plt.rcParams['font.sans-serif'] = ['Simhei']       # 解决可视化过程中的中文显示问题
plt.rcParams['axes.unicode_minus'] = False

2、导入数据、查看、抽样

(1)读取、查看

# 读取数据
data_user = pd.read_csv("tianchi_mobile_recommend_train_user.csv",
            encoding = "utf-8",dtype = str)

#  查看数据基础情况
data_user.info()

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 12256906 entries, 0 to 12256905
Data columns (total 6 columns):
user_id          object
item_id          object
behavior_type    object
user_geohash     object
item_category    object
time             object
dtypes: object(6)
memory usage: 561.1+ MB

字段解释:

'''
字段解释:
user_id: 用户身份
item_id: 商品ID
behavior_type: 用户行为类型(点击、收藏、加购物车、支付---1,2,3,4表示)
user_geohash: 地理位置
item_category: 品类(商品所属的品类)
time: 用户行为发生的时间
'''

(2)抽样

# 整体数据量太大,随机抽取20%来操作
data_user = data_user.sample(frac = 0.2,replace = False)

# 抽取的数据情况:
data_user.info()

输出:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 2451381 entries, 2927950 to 9650036
Data columns (total 6 columns):
user_id          object
item_id          object
behavior_type    object
user_geohash     object
item_category    object
time             object
dtypes: object(6)
memory usage: 130.9+ MB
# 数据前五行:
data_user.head()

输出:


1

3、数据预处理

(1)查看数据缺失情况

# 数据完整度
data_user.isnull().sum()     # 使用 isnull()查看数据缺失情况

输出:

user_id                0
item_id                0
behavior_type          0
user_geohash     1666852
item_category          0
time                   0
dtype: int64

可见数据缺失的主要是用户地理信息

计算缺失率

# 计算缺失率
data_user.apply(lambda x:sum(x.isnull())/len(x))    # 使用 lambda() 函数

输出:

user_id          0.000000
item_id          0.000000
behavior_type    0.000000
user_geohash     0.680321
item_category    0.000000
time             0.000000
dtype: float64

由于地理对于此次分析 影响不大,故忽略地理信息的缺失

(2)对日期进行处理

# 拆分time,使用切片:
data_user['date'] = data_user['time'].str[:10]     # 提取出日期“yyy-mm-dd”格式的
data_user['hour'] = data_user['time'].str[11:]     # 因为日期和时间中间有空格,故从11开始切片

# 查看数据类型
# data_user.dtypes
data_user.head()

输出:


2

对 time、date 和 hour进行数据类型的转换

# 转换日期的数据类型
data_user['time'] = pd.to_datetime(data_user['time'])     # 使用 to_datetime()
data_user['date'] = pd.to_datetime(data_user['date'])
data_user['hour'] = data_user['hour'].astype(int)
# 再次查看数据类型
data_user.dtypes

输出:

user_id                  object
item_id                  object
behavior_type            object
user_geohash             object
item_category            object
time             datetime64[ns]
date             datetime64[ns]
hour                      int32
dtype: object

(3)对数据进行排序

# 按 time 这一列进行升序排列,并对原数据进行操作

data_user.sort_values(by = 'time',ascending = True,inplace = True)   
 # 注意 inplace的用法,当 =True时,会直接在元数据 data_user里进行修改

data_user.tail()

输出:


3

可见最后的 time 是12月18号

(4)重置索引列

# 删除索引,并重置
data_user.reset_index(drop = True,inplace = True)       # .reset_index()

data_user.head()

输出:


4

(5)数据快速统计摘要

data_user.describe(include = "all")

# 对数据进行简单评估,没有问题则数据清洗工作结束

输出:


5

4、构建数据模型

(1)pv和uv值的变化

从日期来看

1、日访问量pv

pv_daily = data_user.groupby('date').count()['user_id']    # 日访问量即每天的浏览量,对访客ID不必去重

display(pv_daily.head())

输出:

date
2014-11-18    73216
2014-11-19    72211
2014-11-20    70879
2014-11-21    67017
2014-11-22    72098
Name: user_id, dtype: int64

2、日访客量uv

uv_daily = data_user.groupby('date')['user_id'].apply(lambda x:x.drop_duplicates().count())

display(uv_daily.head())

输出:

date
2014-11-18    5660
2014-11-19    5688
2014-11-20    5632
2014-11-21    5558
2014-11-22    5474
Name: user_id, dtype: int64

3、合并pv和uv,并重新保存

pv_uv_daily = pd.concat([pv_daily,uv_daily],axis = 1)    # 拼接使用 pd.concat()
# 在pandas中用concat()函数对两个表进行拼接,axis = 1,就是按列拼接

pv_uv_daily.columns = ['pv','uv']       # 设置字段名

pv_uv_daily.head()

输出:


6

4、查看pv和uv之间的相关性

使用系数相关矩阵 DataFrame.corr(method=‘pearson’, min_periods=1),计算列与列之间的相关系数,返回相关系数矩阵。
method:可选值为{‘pearson’, ‘kendall’, ‘spearman’}

pv_uv_daily.corr(method = 'pearson')  # 越接近“1”,线性相关性越大

pv_uv_daily.corr(method = 'spearman')

输出:


7

可见pv和uv之间有正向关系

5、画pv和uv的图(日期)

plt.figure(figsize = (16,9))     # 设置画布大小,宽16,高9

figure函数用法:
''' figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)

num:图像编号或名称,数字为编号 ,字符串为名称 figsize:指定figure的宽和高,单位为英寸;
dpi参数:指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80 1英寸等于2.5cm,A4纸是 21*30cm的纸张
facecolor:背景颜色
edgecolor:边框颜色
frameon:是否显示边框

详解见:figure函数的用法
'''

plt.subplot(211)    # 使用subplot绘制多个子图,211意思是两行一列,占用第一个 
plt.plot(pv_daily,color = 'blue')

plt.ylabel('访问量')       # y轴标签
plt.title('每日访问量')    # 子图表头标题
plt.legend()               # 图例

plt.subplot(212)        # 使用subplot绘制多个子图,212意思是两行一列,占用第2个 
plt.plot(uv_daily,color = 'red')
# pv_uv_daily['uv'].plot(color = 'red')
plt.xlabel('日期')             # X轴标签
plt.ylabel('访客量')            # y轴标签
plt.title('每日访客数')         # 子图表头标题
plt.legend()                   # 图例


plt.suptitle('pv和uv变化趋势',fontsize = 25,color = 'blue')     # 大图主表头标题,字号15,蓝色
plt.show()

# plt.show()
plt.savefig('PV和UV变化趋势.png', bbox_inches='tight')

plt.subplot(221) //分成2x2,占用第一个,即第一行第一列的子图
plt.subplot(222)//分成2x2,占用第二个,即第一行第二列的子图
plt.subplot(212)//分成2x1,占用第二个,即第二行

输出:


在这里插入图片描述

可见,在双12期间访问量和访客量都达到峰值

从小时来看

1、整理每日时间段的pv和uv数据(类比按日期的代码意思)

pv_hour = data_user.groupby('hour').count()['user_id']
uv_hour = data_user.groupby('hour')['user_id'].apply(lambda x:x.drop_duplicates().count())

pv_uv_hour = pd.concat([pv_hour,uv_hour],axis = 1)
pv_uv_hour.columns = ["pv","uv"]
pv_uv_hour.head()

输出:

8
2、查看相关性
# 查看pv_hour和 uv_hour 之间的相关系数
pv_uv_hour.corr("pearson")

pv_uv_hour.corr('spearman')

输出:


8

从相关性上来看,可以看出每小时访问量和每小时访客量呈正相关

3、绘制每小时的pv和uv 图(小时)

plt.figure(figsize = (16,9))       # 设置画布大小

pv_uv_hour['pv'].plot(color = 'r',label = "访问量")    
plt.ylabel('访问量')
plt.xticks(range(0,24),pv_uv_hour.index)
# 对于xticks(locs, [labels], **kwargs)里面的各个参数locs是设置显示有几个刻度,
# [labels]是在每个刻度下显示的标签,
# **kwargs可用于设置标签字体倾斜度rotation和颜色等

plt.legend()
plt.show()

输出:


9
plt.figure(figsize = (16,9))  

pv_uv_hour['uv'].plot(color = "blue",label = "访客量")
plt.ylabel('访客量')
plt.xticks(range(0,24),pv_uv_hour.index)

plt.legend()
# plt.show()

plt.savefig('uv(小时).png', bbox_inches='tight')

输出:


10

合并两个pv和uv图形在同一个坐标轴里

# 合并两个pv和uv图形在同一个坐标轴里
plt.figure(figsize = (16,9))

pv_uv_hour['pv'].plot(color = 'b',label = '访问量')
plt.ylabel('访问量')
plt.legend()

pv_uv_hour['uv'].plot(color = 'r',label = '访客量',secondary_y = True)  # 应用在第二Y轴上
plt.ylabel('访客量')
plt.xticks(range(0,24),pv_uv_hour.index)
plt.legend(loc='upper center')   # 位置中间

plt.grid(True)
# plt.show()

plt.savefig('每小时pv和uv图.png', bbox_inches='tight')
11

总结:
从上图看出:时段0-5点,pv和uv波动情况相同,并同时呈现下降趋势;
18点后用户的活跃度达到一天的峰值;
5-10点是活跃度攀升的时间段;
10-18点用户活跃度稳定。

(2)用户在一天不同时间段内的访问量及不同行为类型统计

pv_detail = pd.pivot_table(columns = 'behavior_type',index = 'hour',
                           data = data_user,aggfunc = np.size,values = 'user_id')    # 数据透视

pv_detail.columns = ['点击','收藏','加购物车','支付']       # 改变字段的名称

display(pv_detail.head())

输出:


12

绘制图形:

# 由于点击量(1)和其他行为类型相差太大,不适合在统一坐标轴展示,此处提出点击量1
plt.figure(figsize = (16,9))

# sns.lineplot(data = pv_detail)     # 全部显示
sns.lineplot(data = pv_detail.iloc[:,1:])    # 剔除点击量

# plt.show()
plt.savefig('一天内用户行为分布.png', bbox_inches='tight')

输出:


在这里插入图片描述

(3)将用户行为转化为漏斗计算

# 查看不同用户行为类型的访问量
user_type_count = data_user.groupby('behavior_type').count()
# user_hh = pd.DataFrame(list(user_type_count),index = [1,2,3,4],columns = ['行为','总数'])

user_type_count = user_type_count['user_id']
# user_type_count
user_hh = pd.DataFrame(list(user_type_count),index = ['点击','收藏','加购物车','支付'],columns = ['数量'])
user_hh

输出:


13

画漏斗模型,pyecharts制图

# funnel = Funnel( "漏斗图示例")

# name = "漏斗图示例"
# attr = ['点击','收藏','加购物车','支付'] 
# value = user_hh["数量"]


# funnel.add(
#     name,
#     attr,
#     value,
#     is_label_show=True,
#     label_pos="outside",
#     legend_orient="vertical",
#     legend_pos="left",
# )
# funnel.render()

(4)计算流失率

# (1)点击量到收藏的流失率
rate1 = (user_type_count[0]-user_type_count[1])/user_type_count[0]

# (2)点击量到加购的流失率
rate2 = (user_type_count[0]-user_type_count[2])/user_type_count[0]

# (3)点击到支付的流失率
rate3 = (user_type_count[0]-user_type_count[3])/user_type_count[0]

# (4)加购到购买的流失率
rate4 = (user_type_count[2]-user_type_count[3])/user_type_count[2]

print(rate1)
print(rate2)
print(rate3)
print(rate4)

输出:

0.979064047403986
0.9704118937573873
0.9895603722620376
0.64716810016968

建议:
发现流失率太大,浏览到收藏或加购 这一过程流失很大一部分,可能是用户花费很长时间选购合适的商品,可以优化平台的推荐算法,或者优化筛选栏,尽量减少用户浏览商品花费的时间,并将流程指标再细化后进行分析,找出影响用户流失的关键问题

针对浏览量高而销量不高的这部分商品,商家可以从以下几个方面提高销售额:
1.诚信吸引用户,有的商家为吸引用户点击,在商品展示页投放的价格具有较强吸引力,而实际价格偏高,反而造成用户流失;

2.从用户角度出发设计详情页信息流展示,便于用户获取信息;

3.优化商品展示的形式,可以采用视频等更直观的展示方式;

4.评论区评价管理,尤其对于差评区的用户反馈进行认真对待,分析自身劣势,并做出积极的回应和弥补。

(5)计算用户消费次数

用户消费次数

# 用户消费次数
per_buy = data_user[data_user.behavior_type == '4'].groupby('user_id').size()
per_buy.head(5)

输出:

user_id
100001878     3
100012968     3
100014060     3
100024529     8
100027681    15
dtype: int64

快速统计:

# 用户消费次数的分布情况--快速统计
per_buy.describe()

输出:

count    6644.000000
mean        3.599338
std         4.525364
min         1.000000
25%         1.000000
50%         2.000000
75%         4.000000
max       163.000000
dtype: float64

发现用户消费次数的平均数mean在小于4次,需要重点关注消费小于4次的用户群体

统计消费用户的日消费次数

# 统计每位消费用户的日消费次数
day_buy = data_user[data_user['behavior_type'] == '4'].groupby(['date','user_id']).count()['behavior_type']

day_buy = day_buy.reset_index().rename(columns = {'behavior_type':'total'})  # 重置索引为默认索引,并修改列名为toatl

day_buy.head()

输出:

14
其它消费数据
# 日消费次数
tt = day_buy.groupby('date')['total'].sum()

# 日消费人数 
pp = day_buy.groupby('date')['user_id'].count()

# 每日人均消费次数
renjun_buy = tt/pp

display(renjun_buy.head())

输出:

date
2014-11-18    1.393474
2014-11-19    1.422509
2014-11-20    1.384000
2014-11-21    1.364465
2014-11-22    1.593607
dtype: float64

绘图每日人均消费次数

renjun_buy.describe()    # 对每日人均消费次数快速统计

输出:

count    31.000000
mean      1.393146
std       0.074626
min       1.310476
25%       1.359393
50%       1.377320
75%       1.401906
max       1.705186
dtype: float64

绘图

plt.figure(figsize = (20,9))
sns.lineplot(data = renjun_buy,label = '每日人均消费次数')

plt.show()

输出:


15
# 用户活跃统计 ,同一天,不同用户不同类型的商品id数量统计
user_count = data_user.groupby(['date','user_id','behavior_type']).count()['item_id'].reset_index().rename(columns = {'item_id':'total'})

user_count.head()

输出:


16

(6)计算成交率

成交率 = 付费人数/活跃人数

# 每日用户活跃总次数
huoyue_count = user_count.groupby('date')['total'].sum()
# display(huoyue_count)

# 每日用户付费次数
fufei_count = user_count[user_count['behavior_type'] == '4'].groupby('date')['total'].sum()
# display(fufei_count)

# 一日内的付费用户占比:
zhanbi_rate = fufei_count/huoyue_count
plt.figure(figsize = (16,9))
zhanbi_rate.plot()
plt.xlabel("日期")
plt.ylabel('成交率')
plt.show()

输出:


17

可见在双12 成交率偏高

(7)计算复购率

复购率 = 二次消费以上用户/总消费用户

data_rebuy = data_user[data_user['behavior_type'] == '4'].groupby('user_id')['date'].apply(lambda x:len(x.unique()))
# .apply(lambda x:len(x.unique()))
# data_tebuy:用户在不同日期的购买次数,这段代码相当于数据透视表,
# 用户行为放筛选栏,选购买的;用户ID放“行”,“date”放"值",然后函数apply是对日期进行去重             
            
data_rebuy[data_rebuy>=2].count()/data_rebuy.count()     #  购买次数大于2的用户数量/所有的购买用户数量              

输出:

0.6243997599039616

5、用户价值分层(RFM模型)

(1)计算R和F

由于数据缺少M(消费金额),因此暂时通过R(最近消费时间)和F(消费频率)的数据来对客户价值进行分层

计算 R,最近购买时间,以2014-12-20为最后日期,计算距上次消费时间多久

# 计算 R,最近购买时间,以2014-12-20为最后日期,计算距上次消费时间多久
recent_buy_time = data_user[data_user['behavior_type'] == '4'].groupby('user_id')['date'].apply(lambda x:datetime(2014,12,20) - x.sort_values().iloc[-1]) 

recent_buy_time.head()

输出:

user_id
100001878   2 days
100012968   2 days
100014060   2 days
100024529   8 days
100027681   7 days
Name: date, dtype: timedelta64[ns]

对输出进行处理,重置索引和修改字段名

recent_buy_time = recent_buy_time.reset_index().rename(columns = {'date':'recent'})

recent_buy_time['recent'] = recent_buy_time['recent'].map(lambda x:x.days)  # 将天数提取出来使用 .map(lambda)

 
recent_buy_time.head()

结果:

18

计算F,计算这段时间里,用户的购买次数

# 计算F
buy_freq = data_user[data_user["behavior_type"] == '4'].groupby('user_id')['date'].count().reset_index().rename(columns = {'date':'freq'})

buy_freq.head()

输出:


19

将R和F的结果拼接,用.merge()

RFM = pd.merge(recent_buy_time,buy_freq,on = 'user_id')
# RFM = pd.merge(recent_buy_time,buy_freq,left_on = 'user_id',right_on = 'user_id')

RFM.head()
20

(2)数据分箱

# 进行数据分箱
RFM['recent_value'] = pd.qcut(RFM.recent,2,labels = ['1','0'])    # 数据分箱   对recent进行二分,recent小的设为1,大的设为0
RFM['freq_value'] = pd.qcut(RFM.freq,2,labels = ['0','1'])       # 数据分箱,   对freq进行二分,freq大的设为1,小的设为0

RFM.head()

21
RFM['RFM'] = RFM['recent_value'].str.cat(RFM['freq_value'])    # pandas中多列拼接成一列的函数

RFM.sample(10)
22

查看RFM列的等级分布

# 查看RFM列的等级分布
RFM['RFM'].value_counts()    # 查看某列中有哪些不同的值,并计算每个值有多少个重复值

输出:

11    2262
00    2132
10    1347
01     923
Name: RFM, dtype: int64

(3)划分等级

# 对不同等级进行 级别标记,重要性从高到低
def trans_value(x):          # 注意括号里的X
    if x == '11':
        return '重要价值用户:近期多次消费'
    elif x == '10':
        return '重要发展客户:近期少量消费'
    elif x == '01':
        return '重要保持用户:历史多次消费'
    elif x == '00':
        return '一般价值用户:历史少量消费'



RFM['用户等级'] = RFM['RFM'].map(trans_value)

RFM.sample(5)

输出:


23

(3)客户等级的可视化处理

RFM['用户等级'].value_counts()

输出:

重要价值用户:近期多次消费    2262
一般价值用户:历史少量消费    2132
重要发展客户:近期少量消费    1347
重要保持用户:历史多次消费     923
Name: 用户等级, dtype: int64

对客户等级做可视化处理展示

# 对客户等级做可视化处理展示
plt.figure(figsize = (16,9))

RFM['用户等级'].value_counts().plot(kind = 'barh') 
plt.xlabel('数量')

plt.show()

输出:


24

画出饼状图:

plt.figure(figsize = (16,9))
plt.pie(RFM['用户等级'].value_counts(),labels = ['重要价值用户:近期多次消费','一般价值用户:历史少量消费','重要发展客户:近期少量消费','重要保持用户:历史多次消费'],autopct = '%1.2f%%',colors = ('b','g','r','y'))
# 画饼图,pie(数据,数据对应的标签,百分数保留两位小数,颜色),labels = RFM['用户等级'].unique()
plt.title('客户等级占比')

plt.show()
输出: 25

6、总结和建议

对于重要价值用户:近期多次消费,这些人最优质的,要重点关注并且保持,应该提高满意度,增加留存
对于重要保持用户:最近有消费,但消费频率不高,可以通过活动来刺激消费,提高消费频次
对于重要发展用户:最近没有购买,但是历史上购买频次较高,可以做触达,防止客户流失
对于一般价值用户:由于历史消费较少,最近也没消费记录,因此需要防止流失,可以推送优惠券或者针对项活动,再次唤醒购买意愿

整体结论和建议:
1、客户流失率较高:优化搜索匹配度和商品内容详情,根据用户喜好推荐;诚信页面展示,降低负面评论;随机选取用户进行问问卷调查,采纳客户建议
2、根据pv和uv,日期和时段的分布情况:在双十二活动期间可以加大营销力度,另外在每天下午18点后的用户活跃高峰期,推出营销活动,使更多的人知道
3、根据回购率情况:应将重点放在培养转化老顾客经常回购的习惯,适当情况通过给老用户优惠的活动,培养顾客忠诚度

4、通过RFM模型:对不同等级的用户采取不同的营销策略,分为重要客户维护、较重要客户再开发、一般客户争取。一般通过各种活动,分层次进行营销。

相关文章

网友评论

      本文标题:某店铺双12前后消费行为分析

      本文链接:https://www.haomeiwen.com/subject/dqoxlktx.html