电商、互联网、金融这三驾马车是对数据分析应用最为广泛的行业,同时也占据了就业市场上绝大多数的数据分析岗位,只因日常业务产生的海量数据蕴含着无尽的价值。 本次就通过电商角度,选取阿里天池项目中的淘宝App用户行为数据利用Python进行数据分析。
通过对用户关键行为的埋点获取的日志数据,包含用户、商品、行为、时间等信息,而看似简单的几个维度,通过数据分析手段,便能从不同角度挖掘蕴含的价值。 本次主要通过以下四个方向探索淘宝用户行为:
PV、UV随时间变化。 留存率模型。
各周期内消费次数统计。 各行为转化模型。 复购率模型。 回购率模型。
RFM模型。 各价值类别用户分布、购买力等。
商品和行为关系。 TOP商品分析。
数据中包含了淘宝App由2019年11月28日至2019年12月3日之间,有行为的随机用户的所有行为(行为包括点击、购买、加购、收藏)。由user_id(用户ID)、goods_id (商品ID)、cat(商品类目ID)、behavior(行为类型)、time(时间戳)、sex(性别)、addr(城市)、device(访问设备)、price(商品单价)、amount(商品销量)组成,并以逗号分隔。
源数据如图
******************** 基本信息
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 757565 entries, 0 to 757564
Data columns (total 10 columns):
user_id 757565 non-null int64
goods_id 757565 non-null int64
cat 757565 non-null int64
behavior 757565 non-null object
time 757565 non-null int64
sex 757565 non-null int64
addr 757565 non-null object
device 757565 non-null object
price 757565 non-null float64
amount 757565 non-null int64
dtypes: float64(1), int64(6), object(3)
memory usage: 57.8+ MB
None
******************** 空值
user_id 0
goods_id 0
cat 0
behavior 0
time 0
sex 0
addr 0
device 0
price 0
amount 0
dtype: int64
******************** 行为项
pv 679668
cart 42714
fav 20601
buy 14582
Name: behavior, dtype: int64
******************** 重复值
False 757565
dtype: int64
数据很干净,只是有些数据类型需要转换,之后随用随改吧。
df["time"]=df["time"].apply(lambda x:datetime.datetime.fromtimestamp(x))
df['date'] = df['time'].dt.date
df['week'] = df['time'].dt.dayofweek+1
df['hour'] = df['time'].dt.hour
pv、uv 按天分析,观察其访问走势
puv_pivot = pd.pivot_table(df, index=['date'], values=['user_id'], aggfunc='count')
uv = df[['user_id','date']].drop_duplicates()['date'].value_counts()
puv_pivot = puv_pivot.join(uv)
puv_pivot.columns = ['pv','uv']
puv_pivot['avg_pv'] = puv_pivot['pv']/puv_pivot['uv']
grid = Grid()
bar = Bar()
grid.theme = ThemeType.PURPLE_PASSION
line = Line()
line.add_xaxis([str(i)[:10] for i in puv_pivot.index.tolist()])
line.add_yaxis("pv", puv_pivot["pv"].tolist(), label_opts=opts.LabelOpts(is_show=False))
line.extend_axis(yaxis=opts.AxisOpts(type_="value",name="uv人数",position="right", axislabel_opts=opts.LabelOpts(formatter="{value}")))
line.set_global_opts(yaxis_opts=opts.AxisOpts(
name="pv人数",
type_="value",
axislabel_opts=opts.LabelOpts(formatter="{value}")
),
xaxis_opts=opts.AxisOpts(name="",axislabel_opts={"rotate":45}),
title_opts=opts.TitleOpts("pv uv 变化趋势"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
) # 交叉指向工具
line.add_xaxis([str(i)[:10] for i in puv_pivot.index.tolist()])
line.add_yaxis("uv", puv_pivot["uv"],yaxis_index = 1,label_opts=opts.LabelOpts(is_show=False))
line.render_notebook()
可以发现,PV与UV的每日变化趋势大致相同:工作日维持在低值,12月2日PV与UV有较大幅度地提升,检索可知正值“双十二”前夕,各类预热活动促进用户访问增长。
behavior_pivot = pd.pivot_table(df,index='date',columns='behavior',values='user_id',aggfunc='count')
构图方式同 pv uv每日变化趋势 ,这里只展示可视化结果
由于浏览量与其他行为不在同一个量级,故将浏览量置于次坐标轴展示。从变化趋势来看,12月第一天迎来了各类行为的峰值。
gp_hour = df.groupby('hour')['user_id'].count()
line = (
Line()
.add_xaxis(gp_hour.index.tolist())
.add_yaxis("访问量", gp_hour.values.tolist(),label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="各时段访问量"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
yaxis_opts=opts.AxisOpts(name="访问量"),
xaxis_opts=opts.AxisOpts(name="时段",axislabel_opts={"rotate":0})
)
)
line.render_notebook()
晚上(19-23时)是用户访问淘宝App的活跃时段,早上(6-10时)是用户访问淘宝App的增长迅速时段。
behavior_pivot_h = pd.pivot_table(df,index='hour',columns='behavior',values='user_id',aggfunc='count')
line = Line()
line.add_xaxis([str(i)[:10] for i in behavior_pivot_h.index.tolist()])
line.add_yaxis("buy",behavior_pivot_h["buy"].tolist(),label_opts=opts.LabelOpts(is_show=False))
line.add_yaxis("cart",behavior_pivot_h["cart"].tolist(),label_opts=opts.LabelOpts(is_show=False))
line.add_yaxis("fav",behavior_pivot_h["fav"].tolist(),label_opts=opts.LabelOpts(is_show=False))
line.extend_axis(yaxis=opts.AxisOpts(type_="value",
name="pv人数",
position="right",
axislabel_opts=opts.LabelOpts(formatter="{value}"),
))
line.set_global_opts(yaxis_opts=opts.AxisOpts(
name="buy cart fav 人数",
type_="value",
axislabel_opts=opts.LabelOpts(formatter="{value}")
),
xaxis_opts=opts.AxisOpts(name="",axislabel_opts={"rotate":0}),
title_opts=opts.TitleOpts("各时段行为变化趋势"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
) # 交叉指向工具
line.add_xaxis([str(i)[:10] for i in behavior_pivot_h.index.tolist()])
line.add_yaxis("pv",
behavior_pivot_h["pv"],
yaxis_index = 1,
label_opts=opts.LabelOpts(is_show=False))
line.render_notebook()
1.用户从0点到6点处于一个休息状态,而从6点开始,到10点活跃的人数越来越多,10点达到了一个巅峰,然后又逐渐回落,预测是用户起床上班,利用路上通勤时间进行浏览以及购买,而到了上班时间,则只能抽空购物; 2.晚上6点到9点用户数量又开始激增,成交率也增加,证明用户下班,吃饭等等有较多的空闲时间进行购物了;10点之后用户浏览慢慢下降,是准备要休息了。
所以我们能看出来,利用用户的空闲时间进行营销,比如早上通勤时间,中午吃饭时间,晚上6-9点,能够提升用户成交率。
观察每日新增用户情况。新用户的定义:第一次访问网站
new_visitor=df.groupby('user_id')['date'].min().value_counts()
new_visitor
# last_visitor=df.groupby('user_id')['date'].max().value_counts()
# last_visitor
bar = (Bar()
.add_xaxis(new_visitor.index.tolist())
.add_yaxis("",new_visitor.values.tolist() )
.set_global_opts(
title_opts=opts.TitleOpts(title="每日新增用户量"),
yaxis_opts=opts.AxisOpts(name="人数"),
xaxis_opts=opts.AxisOpts(name="日期",axislabel_opts={"rotate":30})
)
)
bar.render_notebook()
程序逻辑:
def Retention(x, n):
user = []
date = pd.Series(x.date.unique()).sort_values()[:-n]
print(date)
keep_rates = []
for i in date:
# print(i)
new_user = set(x.loc[x.date==i].user_id.unique()) - set(user)
user.extend(new_user)
user_n_day = x.loc[x.date==i + datetime.timedelta(n)].user_id.unique()
# print(user_n_day)
a=0
for user_id in user_n_day:
if user_id in new_user:
a += 1
rates = a/len(new_user)
# print(keep_rates)
keep_rates.append(rates)
data_retention=pd.Series(keep_rates,index=date)
return data_retention
data_retention=Retention(df,1)
print(data_retention)
line = (
Line()
.add_xaxis(data_retention.index.tolist())
.add_yaxis("留存率", data_retention.values.tolist(),label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="留存变化"),
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
yaxis_opts=opts.AxisOpts(name=""),
xaxis_opts=opts.AxisOpts(name="时间",axislabel_opts={"rotate":0})
)
)
line.render_notebook()
0 2019-11-28
1 2019-11-29
2 2019-11-30
3 2019-12-01
4 2019-12-02
dtype: object
2019-11-28 0.791853
2019-11-29 0.668347
2019-11-30 0.666667
2019-12-01 0.954301
2019-12-02 0.960784
dtype: float64
不同间隔的留存率均呈现同一种变化状态:整体呈逐日递减趋势,但是均在倒数第二天迎来小高峰,对应的现实场景则为12-2这一天的表现使得整体留存率得到大幅度的提升。
通过漏斗分析,我们可以发现在一个多步骤过程中每一步的转化和流失情况。 本案例的漏斗中,流程顺序为点击-加入购物车-收藏-支付(假设以上步骤只能依次进行或中断,不能跳过中间过程到下个节点)。 程序逻辑:分别计算进入各个环节的用户量,再分别比较。
def cal_funnel(data,timetype):
gp_day_beh = df.groupby([timetype,'behavior']).user_id.count().reset_index()
date = pd.Series(gp_day_beh[timetype].unique())
rates=[]
for day in date:
print(day)
gp_day = gp_day_beh[gp_day_beh[timetype]==day]
# print(gp_day.head(1))
# pv = gp_day[gp_day.behavior=='pv'].reset_index().loc[0,'user_id']
pv=1
pv_to_cart = gp_day[gp_day.behavior=='cart'].reset_index().loc[0,'user_id']/gp_day[gp_day.behavior=='pv'].reset_index().loc[0,'user_id']
# print(pv_to_cart)
cart_to_fav = gp_day[gp_day.behavior=='fav'].reset_index().loc[0,'user_id']/gp_day[gp_day.behavior=='cart'].reset_index().loc[0,'user_id']
fav_to_buy = gp_day[gp_day.behavior=='buy'].reset_index().loc[0,'user_id']/gp_day[gp_day.behavior=='fav'].reset_index().loc[0,'user_id']
rate = [pv,pv_to_cart,cart_to_fav,fav_to_buy]
print(rate)
rates.append(rate)
funnel = pd.DataFrame(rates,index=date,columns=['pv','pv_to_cart','cart_to_fav','fav_to_buy'])
return funnel
day_funnel = cal_funnel(df,'date')
day_funnel
# hour_funnel = cal_funnel(df,'hour')
# hour_funnel
gp_behavior = df.groupby(['behavior'])['user_id'].count()
index = gp_behavior.index.tolist()
values = gp_behavior.values.tolist()
data = [[index[i],
int(values[i])*100/max(values)] for i in range(len(index))]
funnel=(
Funnel(init_opts=opts.InitOpts(width="800px", height="600px"))
.add( series_name="", data_pair=data, gap=2,
tooltip_opts=opts.TooltipOpts(trigger="item", formatter="{a} <br/>{b} : {c}%"),
label_opts=opts.LabelOpts(is_show=True, position="inside"),
itemstyle_opts=opts.ItemStyleOpts(border_color="#fff", border_width=1),)
.set_global_opts(title_opts=opts.TitleOpts(title="总体行为转化", subtitle=""))
)
funnel.render_notebook()
从上图可以发现用户从浏览点击商品,然后加入购物车,收藏等等,最后到下单购买,而用户收藏和加入购物车并没有必然的联系,不存在上下级,所以把它当做是购物中的一环,由上面的计算我们能看到用户的从点击到收藏和加入购物车,转化率只有6.2%,而到了购买仅有2.15%,转换率非常之低,说明淘宝推荐的商品不是用户喜欢的,或者是用户想要的商品,所以才导致了这么低的转换率。所以接下来,淘宝能够做的就是优化商品的推荐机制,优化用户搜索商品的效率,提升用户从点击到收藏和加入购物车这一环的转化率,这样才能够最终提升用户购买的比例。
复购率是自然周期内,购买多次的用户占比 复购率统计口径:有复购行为的用户数 / 有购买行为的用户数
df_buy = df.loc[df.behavior=='buy']
pivot_life = df_buy.pivot_table(index='user_id',columns = 'date',values='time',aggfunc='count').fillna(0)
pivot_life.head()
repurchase = pivot_life.applymap(lambda x:1 if x>1 else np.NAN if x ==0 else 0)
repurchase.head()
(repurchase.sum()/repurchase.count()).plot(figsize = (10,4))
复购率稳定在 28% 左右
pivot_buy_back = pivot_life.applymap(lambda x: 1 if x>0 else 0)
def buy_return(data):
status = []
for i in range(len(pivot_buy_back.columns)-1):
# print(i)
if data[i] == 1:
if data[i+1] ==1:
status.append(1)
if data[i+1] == 0:
status.append(0)
else:
status.append(np.NaN)
status.append(np.NaN)
return pd.Series(status,pivot_buy_back.columns)
pivot_buy_return = pivot_buy_back.apply(buy_return,axis=1)
pivot_buy_return.head()
1 为回购用户, 0 为前一日没购买当天购买过,NaN 为连续两日都没购买
plt.figure(figsize=(20,4))
plt.subplot(211)
(pivot_buy_return.sum() / pivot_buy_return.count()).plot()
plt.title('用户回购率图')
plt.ylabel('百分比%')
plt.subplot(212)
plt.plot(pivot_buy_return.sum(),label='当日消费人数')
plt.plot(pivot_buy_return.count(),label='当日回购人数')
plt.xlabel('month')
plt.ylabel('人数')
plt.legend()
plt.show()
由回购率图可以看出,用户回购率略低于复购率,约在 24% 左右,波动性较强。 由人数分布图发现,回购人数在前4天趋于稳定,波动产生的原因可能由于“双十二”前夕,各类预热活动导致。
pivot_life = df_buy.pivot_table(index='user_id',columns = 'date',values='time',aggfunc='count').fillna(0)
pivot_life.head()
df_buy_count = pivot_life.applymap(lambda x: 1 if x>0 else 0)
def active_status(data):
status = []
for i in range(len(df_buy_count.columns)):
#若该日没消费
if data[i] == 0:
if len(status) > 0:
if status[i-1] == '未消费':
status.append('未消费')
else:
status.append('不活跃')
else:
status.append('未消费')
#若该日消费
else:
if len(status) == 0:
status.append('第一次消费')
else:
if status[i-1] == '不活跃':
status.append('回流')
elif status[i-1] == '未消费':
status.append('第一次消费')
else:
status.append('活跃')
# 这里需要对返回的值进行转换,将列表转为Series
return pd.Series(status, index = df_buy_count.columns)
purchase_stats = df_buy_count.apply(active_status,axis=1)
purchase_stats.head()
purchase_status_ct = purchase_stats.replace('未消费',np.nan).apply(lambda x:pd.value_counts(x))
# purchase_status_ct
purchase_status_ct.fillna(0).T.head()
主要分为两部分的判断,以当日是否消费为界。当日没有消费,还要额外判断他是不是新客,因为部分用户是11-30日才消费成为新客,那么在前2天他连新客都不是,用未消费表示。如果是老客,则为不活跃。
purchase_status_ct.fillna(0).T.plot.area()
newuser_per = purchase_status_ct.fillna(0).T.apply(lambda x: x/x.sum(),axis= 1 )
line.render_notebook()
RFM模型在客户管理中常被用来衡量客户的价值和创新能力,主要考量三个指标:最近一次消费(Recency)、消费频率(Frequency)、消费金额(Money)。 根据以上三个维度对客户做细分:假定每个维度划分五个等级,得到R值(1-5)、F值(1-5)、M值(1-5)。客户可以被分作125个细分群,可以根据客户的交易行为差异针对不同的群体做不同的推荐。
RFM模型分析前提条件:
df_buy = df.loc[df.behavior=='buy']
rfm_pivot = df_buy.pivot_table(index="user_id",
values = ['price','date','behavior'],
aggfunc = {'date':'max',
'behavior':'count',
'price':'sum'})
rfm_pivot['r'] = (rfm_pivot.date.max()-rfm_pivot.date)/np.timedelta64(1,'D')
rfm_pivot.rename(columns={'behavior':'f','price':'m'},inplace=True)
rfm_pivot = rfm_pivot
rfm_pivot
R表示客户最近一次交易时间的间隔,客户在最近一段时间内交易的金额。 F表示客户在最近一段时间内交易的次数,F值越大,表示客户交易越频繁,反之则表示客户交易不够活跃。 M表示客户在最近一段时间内交易的金额。M值越大,表示客户价值越高,反之则表示客户价值越低。
def rfm_func(x):
level = x.apply(lambda x:'1' if x>=0 else '0')
label = level.r + level.f + level.m
d = {
'111':'重要价值客户',
'011':'重要保持客户',
'101':'重要挽留客户',
'001':'重要发展客户',
'110':'一般价值客户',
'010':'一般保持客户',
'100':'一般挽留客户',
'000':'一般发展客户'
}
result = d[label]
return result
rfm_pivot['label'] = rfm_pivot[['r', 'f', 'm']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
rfm_pivot.head()
rfm_pivot.groupby('label').sum()
use_c = rfm_pivot.groupby('label').count()
use_c.head()
pie_rosetype().render_notebook()
之前重要保持客户的累计消费金额最高,这里重要保持客户的消费人数排名第3,离一般挽留用户差距较大,一般挽留用户有2008人,重要保持客户1167人。
重要挽留客户占比很小,对于这类客户,最近消费时间间隔较远,并且消费频次低,我们需要主动联系客户,调查清楚哪里出现了问题,比如通过短信,邮件,APP推送等唤醒客户。 重要价值的用户也比较少,但是却是一个比较优质的客户,所以可以有针对性地给这类客户提供 VIP服务,比如现在的淘宝VIP会员卡等等。 对于重要发展客户,消费频次低,我们需要提升他的消费频率,可以通过优惠券叠加等活动来刺激消费; 而重要保持客户,消费时间间隔较远,但是消费频次高,有可能就是需要买东西的时候,就高频购买,不需要就不再购物,对于这类客户,需要主动联系,了解客户的需求,及时满足这类用户的需求。
imp_keeper = df_buy_rfm[df_buy_rfm.label=='重要价值客户']
imp_keeper
gp_city_rfm = imp_keeper.groupby(['addr'])['label'].count().sort_values(ascending=False)
gp_city_rfm
bar.render_notebook()
gp_label_hour = df_buy_rfm.groupby(['label','hour'])['user_id'].count()
gp_label_hour = gp_label_hour.unstack().T.fillna(0)
line.render_notebook()
gp_label_sex = df_buy_rfm.groupby(['label','sex'])['user_id'].count()
gp_label_sex = gp_label_sex.unstack()#
gp_label_sex.columns=['w','m']
bar_base().render_notebook()
goods_top10 = df_buy['goods_id'].value_counts().head(10)
c = (
Bar()
.add_xaxis(goods_top10.index.tolist())
.add_yaxis("销售量", goods_top10.values.tolist(), category_gap="60%")
.set_series_opts(itemstyle_opts={
"normal": {
"color": JsCode("""new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 244, 255, 1)'
}, {
offset: 1,
color: 'rgba(0, 77, 167, 1)'
}], false)"""),
"barBorderRadius": [30, 30, 30, 30],
"shadowColor": 'rgb(0, 160, 221)',
}})
.set_global_opts(title_opts=opts.TitleOpts(title="top10商品销量"))
)
c.render_notebook()
goods_pv_top = df.loc[df.behavior=='pv']['goods_id'].value_counts().head(10)
bar.render_notebook()
goods_pv_top = df.loc[df.behavior=='fav']['goods_id'].value_counts().head(10)
bar.render_notebook()
gp_city_top = df_buy[['addr','price']].groupby("addr").sum().sort_values('price',ascending=False)
bar.render_notebook()
gp_sex_PB = df.groupby(['sex','behavior'])['date'].count()
gp_sex_PB = gp_sex_PB.unstack().T
gp_sex_PB.columns = ['w','m']
bar_base().render_notebook()
sex_buy = df_buy[['sex','price']].groupby('sex').sum()
time_list = [list(z) for z in zip(['女','男'],
[round(i,2) for i in sex_buy.price.tolist()])]
pie.render_notebook()
本项目从4个方面分析了用户的行为,并且利用 RFM 模型对用户进行了分类
1、时间维度:在用户的休闲时间段,比如通勤时间7-10点,午饭时间12-13点,以及晚上6-10点之间做促销活动,以及一些相关的营销,这样能够大大增加用户购买的转化率。根据留存监控用户的持续用户行为,防止用户流失。
2、消费行为:根据高流失率环节,给予引导与提示,提高转化率。考虑在客户发生首购行为后,发放特殊优惠,以提高复购率。对于点击量高的商品,要重点分析,优化商品的推荐机制,让用户做到点击即想购买。
3、用户价值:通过RFM模型分析得到的不同类型的用户,应该采取不同的激励方案。 对于占比最高的保持和发展的客户(忠诚度较高,购买能力不足),适当给予折扣或施行捆绑销售销售政策。 对于重要挽留的客户,通过发短信和邮件,或者APP客户端推送等,让客户重新回来消费,此外可以通过一些节日优惠等再次召回客户。 对于重要价值的用户,需要给其提供VIP服务,比如VIP可以得到饿了么优惠券等等。
4、商品分析:对于高浏览量商品,可以将重心转移至定价上,实行差异化定价,以提高购买量。高购买率商品,建议提高曝光率,结合多平台宣传,提高浏览量。明星商品,建议平台给予表扬与内部公开,以保证持续的优质。
本文分享自 Python数据分析实例 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!