本专栏将会从用户行为分析,用户价值分析,用户画像,商品画像,销售预测,基于用户推荐,用户购买力预测入手,手把手带你入门电商数据分析。
数据分析的流程是什么?
- 明确目标
- 获取数据
- 数据探索和预处理
- 分析数据
- 得出结论
- 验证结论
- 结果展现
什么是用户行为?
用户行为就是用户在产品上的产生的行为,像我们逛某宝,某东,某多多,在里面点击的任何一件商品,收藏商品,购买商品等等,任何一切行为都会给运营人员记录到(当然是有价值的才记录)
用户行为分析的价值
对用户的行为进行分析,能了解用户,也能了解自己。比如我能知道一周内那几天的用户量高,一天内那个时间段的用户量高,我就可以在那些时间段做点有价值的东西,比如打广告。也可以分析出哪些商品没人看,点击率低转换率低,是什么问题?
明确目的
数据分析第一步,明确目的
假设一个场景,眼看双11要到了,三只松鼠作为一间高端的零食零售店,眼看着就要到双十一大促销了,针对这种情况,运营人员需要对用户进行数据分析,找出问题并提出优化方案,以便能尽可能提高销售额
分析思路
分析方法
本次用户行为分析的方法论,主要就一点,那就是数据分组聚合操作
用SQL的语言来说就是GROUP BY
他的具体用法是:
DF.groupby('class_id')['stu_id'].count()
这语句的意思是以class_id分组,分别统计stu_id的个数
这个用法将贯穿本章节
AARR模型
AARR模型分别代表Acquisition,Activation,Retention,Revenue
即
- 获取用户 — 日均pv,uv,跳失率
- 提高活跃度 – 时活跃度,日活跃度
- 提高留存率 — 按时间维度查看留存
- 获取收入 – 用户购买率,购买量,回购程度
留存率如何计算
留存用户的含义:在某段时间开始使用产品,经过一段时间后依然在使用的用户
留存率:依旧使用产品的用户量/最初的用户量
复购率与回购率
复购率:在某时间窗口内消费两次及以上在总消费用户中的占比
回购率:在某一个时间窗口消费的用户,在下一个时间窗口依旧消费的占比
漏斗分析
漏斗分析简单来说:就是抽象出某个流程,观察每一步中的流失和转化
现在我们简化电商漏斗分析的节点,分为点击,加购,收藏,购买
当然具体情况应该不止这一点,具体看业务数据
实操流程
- 数据探索
- 数据清理
- 数据类型转化
- 构建模型-- AARR模型
- 数据分析-- 漏斗模型
- 结果解读 – 给出具体的建议
代码讲解部分
数据导入
#先导入必要的包,并且读取数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
g=open('customer_behavior.csv',encoding='utf-8')
date=pd.read_csv(g)
date.head()
数据预处理
筛选数据,清洗数据,格式化数据
data1= data[(data.buy_time>='2019-11-05')&(data.buy_time<='2019-11-13')] #筛选这个时间段的数据
#时间格式处理,将字符串转换为时间格式
import time
from datetime import datetime,timedelta,date
data1['day_id']=pd.to_datetime(data1['day_id'],format='%Y-%m-%d')
#提取出时间中的月份、天、时、星期等维度
data1['month']=data1['day_id'].dt.month
data1['buy_time']=data1['day_id'].dt.date
data1['times']=data1['day_id'].dt.time
data1['hours']=data1['day_id'].dt.hour
data1['weekday']=data1['day_id'].dt.dayofweek+1
data1.head()
AARR模型分析
根据用户行为对用户进行分组计数
behavior_count=data1.groupby('be_type')['cust_id'].count()
behavior_count.head()
"""
be_type
buy 203458 购买量
cart 567531 加购量
fav 302497 收藏量
pv 9145058 点击量
"""
计算流量指标分析:pv,uv等
PV=behavior_count['pv']
print("PV=%d"%PV)
UV=len(data['cust_id'].unique())
print("UV=%d"%UV)
print("平均访问量 PV/UV=%d"%(PV/UV))
"""
PV=9145058
UV=100000
平均访问量 PV/UV=91
"""
计算跳失率
跳失率:只有点击行为的用户数/总用户数,总用户数即uv
data_pv=data1.loc[data1['be_type']=='pv',['cust_id']]
data_fav=data1.loc[data1['be_type']=='fav',['cust_id']]
data_cart=data1.loc[data1['be_type']=='cart',['cust_id']]
data_buy=data1.loc[data1['be_type']=='buy',['cust_id']]
#集合相减,获取只有点击行为的用户数
data_pv_only=set(data_pv['cust_id'])-set(data_fav['cust_id'])-set(data_cart['cust_id'])-set(data_buy['cust_id'])
pv_only=len(data_pv_only)
print('跳失率为:%.2f%%'%(pv_only/UV*100))
"""
跳失率为:5.91%
"""
分析:跳失率为5.91%,数值看上去较小,但跳失率一定程度上反映了商品的受欢迎程度,最好还是结合行业数据和以往数据分析是否处于正常范围。 影响跳失率的相关因素有:商品吸引力、商品加载时长以及流量的质量等。
按天进行PV统计 ,按天进行UV统计
pv_day= data1[data1.be_type=='pv'].groupby('buy_time')['be_type'].count()
uv_day=data1[data1.be_type=='pv'].drop_duplicates(['cust_id','buy_time']).groupby('buy_time')['cust_id'].count()
"""
PV
buy_time
2019-11-05 957020
2019-11-06 973800
2019-11-07 915255
2019-11-08 896779
2019-11-09 937196
2019-11-10 949846
2019-11-11 995060
2019-11-12 1265050
2019-11-13 1255052
"""
"""
UV
buy_time
2019-11-05 69349
2019-11-06 70190
2019-11-07 69450
2019-11-08 69536
2019-11-09 70182
2019-11-10 71558
2019-11-11 72542
2019-11-12 95068
2019-11-13 94874
"""
将他们可视化,这部分涉及matplotlib
attr = pv_day.index
v1 = pv_day.values
v2 = uv_day.values
"""
下面是画图了,不会也不要紧,学东西都是循序渐进的过程
画图代码涉及
去掉部分边框,去掉网格
格式化坐标轴的数据
这部分以后会详细出几期高质量的画图教程
"""
from matplotlib.ticker import EngFormatter
plt.figure(figsize=(10,6.2),dpi=100,facecolor="w")
ax1 = plt.subplot(211)
ax1.plot(attr, v1,color='blue', linewidth=3, linestyle='--')
ax1.set_title("Daily hits trend",size=15,color = 'blue')
for spine in ["top","right"]:
ax1.spines[spine].set_visible(False)
ax1.tick_params(top=False,right=False)
ax1.set_ylabel('PV')
formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
ax1.yaxis.set_major_formatter(formatter1)
#第二幅图
ax2 = plt.subplot(212)
ax2.plot(attr, v2,color='orange', linewidth=3, linestyle=':')
ax2.set_title("Daily Unique Visitors Trend",size=15,color = 'orange')
for spine in ["top","right"]:
ax2.spines[spine].set_visible(False)
ax2.tick_params(top=False,right=False)
formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
ax2.yaxis.set_major_formatter(formatter1)
ax2.set_ylabel('UV')
ax1.grid(False)
ax2.grid(False)
plt.tight_layout()
数据分析:PV、UV两者走势趋势相同,符合正常规律,在11月11号的时候,PV、UV呈上涨趋势,而上周并未出现这种情况,推测为因为双 11活动而带来的流量
按小时进行PV、UV统计
pv_hour=data1.groupby('hours')['cust_id'].count().reset_index().rename(columns={'用户ID':'pv'})
uv_hour=data1.groupby('hours')['cust_id'].apply(lambda x:x.drop_duplicates().count()).reset_index().rename(columns={'用户ID':'时uv'})
继续可视化,得到的是按小时点击量趋势,按小时独立访客数趋势
plt.figure(figsize=(10,6.2),dpi=100,facecolor="w")
ax1 = plt.subplot(211)
ax1.plot(pv_hour['hours'], pv_hour['cust_id'],color='blue', linewidth=3, linestyle='--')
ax1.set_title("Hourly hits trend",size=15,color = 'blue')
for spine in ["top","right"]:
ax1.spines[spine].set_visible(False)
ax1.tick_params(top=False,right=False)
ax1.set_ylabel('PV')
formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
ax1.yaxis.set_major_formatter(formatter1)
ax2 = plt.subplot(212)
ax2.plot(uv_hour['hours'], uv_hour['cust_id'],color='orange', linewidth=3, linestyle=':')
ax2.set_title("Hourly Unique Visitors Trend",size=15,color = 'orange')
for spine in ["top","right"]:
ax2.spines[spine].set_visible(False)
ax2.tick_params(top=False,right=False)
formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
ax2.yaxis.set_major_formatter(formatter1)
ax2.set_ylabel('UV')
ax1.grid(False)
ax2.grid(False)
plt.tight_layout()
数据分析:每天凌晨0-6点是点击量最少的时间,同时也是用户访问量最少的情况;10-22点为用户活跃高峰期,可在用户活跃 高峰期的时候增加活动宣传力度
购买人数与购买率
day_buy_user_num = data1[data1.be_type == 'buy'].drop_duplicates(['cust_id', 'buy_time']).groupby('buy_time')['cust_id'].count()
day_active_user_num = data1.drop_duplicates(['cust_id', 'buy_time']).groupby('buy_time')['cust_id'].count()
day_buy_rate = day_buy_user_num / day_active_user_num
attr = day_buy_user_num.index
v1 = day_buy_user_num.values
v2 = day_buy_rate.values
可视化他们
plt.figure(figsize=(10,6.2),dpi=100,facecolor="w")
ax1 = plt.subplot(211)
ax1.plot(attr, v1,color='blue', linewidth=3, linestyle='--')
ax1.set_title("Daily purchase trend",size=15,color = 'blue')
for spine in ["top","right"]:
ax1.spines[spine].set_visible(False)
ax1.tick_params(top=False,right=False)
ax1.set_ylabel('PV')
formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
ax1.yaxis.set_major_formatter(formatter1)
ax2 = plt.subplot(212)
ax2.plot(attr, v2,color='orange', linewidth=3, linestyle=':')
ax2.set_title("Daily purchase rate trends",size=15,color = 'orange')
for spine in ["top","right"]:
ax2.spines[spine].set_visible(False)
ax2.tick_params(top=False,right=False)
# formatter1 = EngFormatter(places=2, sep="\N{THIN SPACE}") # U+2009
# ax2.yaxis.set_major_formatter(formatter1)
ax2.set_ylabel('PV')
ax1.grid(False)
ax2.grid(False)
plt.tight_layout()
数据分析:购买人数和购买率走势在11月10号之前大致相同,从11号开始购买人数有增加,但与之前相比购买 率在减少,此时应优化产品及增加推广力度。
复购率
复购指两天以上有购买行为,一天多次购买算一次,复购率=有复购行为的用户数/有购买行为的用户总数
df_rebuy = data1[data1.be_type == 'buy'].drop_duplicates(['cust_id', 'day_id']).groupby('cust_id')['day_id'].count()
df_rebuy[df_rebuy >= 2].count() / df_rebuy.count()
"""
0.6357834539478533
"""
复购率还可以,这个数据得和上期数据环比来看
留存率
计算逻辑:识别出指定日期的新用户集合,记用户量为b 得到第n天用户集合 识别、计算指定日期新用户在第n天仍使用产品的数量,记用户量为a 留存率=a/b
def cal_retention(data,n): #n为n日留存
user=[]
date=pd.Series(data.buy_time.unique()).sort_values()[:-n] #时间截取至最后一天的前n天
retention_rates=[]
for i in date:
new_user=set(data[data.buy_time==i].cust_id.unique())-set(user) #识别新用户,本案例中设初始用户量为零
user.extend(new_user) #将新用户加入用户群中
#第n天留存情况
user_nday=data[data.buy_time==i+timedelta(n)].cust_id.unique() #第n天登录的用户情况
a=0
for cust_id in user_nday:
if cust_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
data_retention=cal_retention(data1,3) #求用户的3日留存情况
"""
2019-11-05 0.758306
2019-11-06 0.659058
2019-11-07 0.644157
2019-11-08 0.669378
2019-11-09 0.966176
2019-11-10 0.951292
"""
用户流失漏斗分析
pv_users = data1[data1.be_type == 'pv']['cust_id'].count()
fav_users = data1[data1.be_type == 'fav']['cust_id'].count()
cart_users =data1[data1.be_type == 'cart']['cust_id'].count()
buy_users = data1[data1.be_type == 'buy']['cust_id'].count()
attr = ['点击', '加入购物车', '收藏', '购买']
values = [np.around((pv_users / pv_users * 100), 2),
np.around((cart_users / pv_users * 100), 2),
np.around((fav_users / pv_users * 100), 2),
np.around((buy_users / pv_users * 100), 2)]
"""
[100.0, 6.21, 3.31, 2.22]
在总点击中,有6.21%加入购物车,有3.31%加入收藏,只有2.22%到最后购买
"""
我们也可以做个图看看,漏斗图很多方法做,excel也可以,哪个方便那个来,当然也可以弄得很精美,后面可能考虑出一期漏斗图精美教程
from plotly import graph_objects as go
fig = go.Figure(go.Funnel(
y = ["pv", "cart", "fav", "buy"],
x = [pv_users, cart_users, fav_users, buy_users]))
fig.show()
由上图可以看出,点击到加购之间的这一环节的转化率最低,按这一路径来看,我们可以通过优化点击到加购的这一环节的转化率而间接提升用户的购买
我们除了从总点击量来看,还可以从其他方面来看,比如看看从收藏到加购的转化率是多少
data_AARR=data1.groupby('be_type')['cust_id'].count()
#点击量
pv_value=data_AARR['pv']
#收藏量
fav_value=data_AARR['fav']
#加购量
cart_value=data_AARR['cart']
#购买量
buy_value=data_AARR['buy']
##计算转化率,此处由于实际业务中用户收藏和加购没有先后顺序,所以二者合并后计算转化率
#收藏加购转化率
f_c_value=fav_value+cart_value
f_c_ratio=f_c_value/pv_value
print('收藏加购转化率为:%.2f%%'%(f_c_ratio*100))
"""
收藏加购转化率为:9.51%
"""
方法得融会贯通,数据分析其实就是找到数据间的规律,异常,加以验证