pandas实战:用户消费行为画像
《再见pandas》系列图文继续更新,新增第5个实战项目。
以下是系列图文中两个公开分享的历史文章。
该项目主要对某平台用户消费行为进行画像分析,通过pandas的灵活使用,对月销量、客户复购率、回购率、客户分层、高质量客户、留存率、消费间隔等进行多维度分析。以下为部分节选内容,完整数据和代码可在文末扫码了解👇
首先,加载用户的消费数据。
columns=["user_id","order_dt","order_product","order_amount"]
df = pd.read_csv('data.txt', sep='\s+', names=columns)
user_id:客户ID order_dt:订单日期 order_product:订单产品 order_amount:订单金额
1.统计每个客户购买的总数量和平均金额
使用groupby+agg
聚合的方法得到统计结果,并按order_product降序排序。
(
df.groupby("user_id",as_index=False)
.agg({"order_product":np.sum,"order_amount":np.mean})
.sort_values(['order_product'],ascending=False)
)
2.统计每个月销售额的情况
(
df.groupby("order_month")['order_amount'].sum()
.plot(figsize=(10,6),marker='o')
)
3.每笔订单对应的金额分布
一笔订单对应的总金额分布
df.plot.scatter(x="order_product",y="order_amount")
每个用户每笔订单对应的总金额分布
(
df.groupby("user_id")[['order_product','order_amount']].sum()
.plot.scatter(x="order_product",y="order_amount")
)
4.单个用户的消费行为
plt.figure(figsize=(12,4))
plt.subplot(121)
df.order_amount.hist(bins=30) #订单金额直方图分布
plt.subplot(122)
df.groupby("user_id").order_product.sum().hist(bins=30) #每个用户购买总量的直方图
plt.tight_layout()
反映出大部分人的消费额和购买数量都是较低,符合一般消费规律。
5.复购率分析
复购率定义:在一个月内消费次数2次及以上的用户所占的比例。
首先通过透视表pivot_table
统计每个用户各月的消费次数,然后加工出复购的标识,将每月消费次数2次以上的记为1,一次的记为0,没有消费的记为NaN。
pc = df.pivot_table(index="user_id",
columns="order_month",
values="order_date",
aggfunc="count").fillna(0)
pct = pc.applymap(lambda x:1 if x>=2 else np.NAN if x==0 else 0)
# 按月统计复购率
pct.mean().plot(figsize=(10,6),marker='o')
6.回购率分析
回购率:本月消费并在下月继续消费的客户占比
这里的定义是在一个月之内只要消费次数大于1即可认为是消费。
步骤:
首先,加工出本月有过消费的标识字段,通过轴旋转变为宽表形式。 对if_has_order是否消费变量向上偏移一个单位 计算加工出是否回购变量if_reorder 可视化
pp = (
pc.applymap(lambda x:1 if x > 1 else 0)
.stack()
.to_frame(name='if_has_order')
.reset_index()
)
# 回购计算逻辑
pp['if_has_order_next_month'] = pp['if_has_order'].shift(-1)
pp['if_reorder'] = 0
pp.loc[(pp1['if_has_order'] == 1)&(pp['if_has_order_next_month']==1),'if_reorder'] = 1
pp.loc[(pp1['if_has_order'] == 1)&(pp['if_has_order_next_month']==0),'if_reorder'] = 0
pp.loc[(pp1['if_has_order'] == 0),'if_reorder'] = np.nan
(
pp.pivot_table(index='order_month',values='if_reorder',aggfunc='mean')
.plot(figsize=(10,6),marker='o')
)
整体回购率约为25%,其中新客户质量低于老客户,老客户的忠诚度较高。最后一期降为0是由于没有下一期数据,可以视为异常忽略。
7. 客户分层分析
根据客户的活跃程度可将客户分为沉默户、新户、活跃户、不活跃户、回流用户,具体定义如下:
沉默户:从未发生过消费的客户
新户:第一次消费的客户
活跃户:老客户,在时间窗口内发生过消费的客户
不活跃户:老客户,在时间窗口内未发生过消费的客户
回流:上个月未消费但本月消费过的客户
为了给每个客户在各观察月打上客户分层标签,需要借助一些辅助列。通过分组内偏移、排序、累计求和等方法实现。分组内的各种骚操作可以了解东哥的pandas进阶宝典。
pp['order_month'] = pd.to_datetime(pp['order_month'])
pp = pp.sort_values(['user_id','order_month'],ascending=[True,True])
# 加工辅助列
pp['if_has_order_last_month'] = pp.groupby(['user_id'])['if_has_order'].transform(lambda x:x.shift(1))
pp['if_has_order_next_month'] = pp.groupby(['user_id'])['if_has_order'].transform(lambda x:x.shift(-1))
pp['order_rank'] = pp.groupby(['user_id'])['order_month'].transform(lambda x: x.rank(method='first'))
pp['order_cumsum'] = pp.groupby(['user_id'])['if_has_order'].transform('cumsum')
然后,生成客户分层的变量user_status,按照不同的条件进行赋值。
pp['user_status'] = ''
# silent
pp.loc[(pp['order_cumsum']==0),'user_status'] = 'silent'
# new
pp.loc[(pp['order_rank']==1)&(pp['if_has_order']==1),'user_status'] = 'new'
pp.loc[(~(pp['order_rank']==1))&(pp['if_has_order']==1)&(pp['order_cumsum']==1),'user_status'] = 'new'
# unactive
pp.loc[(pp['order_cumsum']>0)&(pp['if_has_order']==0),'user_status'] = 'unactive'
# active
pp.loc[(pp['order_cumsum']>1)&(pp['if_has_order']==1)&(pp['if_has_order_last_month']==1),'user_status'] = 'active'
# return
pp.loc[(pp['order_cumsum']>1)&(pp['if_has_order']==1)&(pp['if_has_order_last_month']==0),'user_status'] = 'return'
最后用面积图进行分层客户的可视化。蓝色的面积表示活跃客户,绿色表示回流客户,4个月后基本稳定,说明没有新客。
pp1 = pp.replace("silent",np.NaN)
pp2 = pp1.pivot_table(index='order_month',columns='user_status',values='user_id',aggfunc='count',fill_value=0)
pp2.plot.area(figsize=(12,6))
8.高质量客户分析
按客户ID分组对订单金额求和,然后计算每个客户的订单总和占累计求和的比例。
ua = df.groupby("user_id").order_amount.sum().sort_values().reset_index()
ua["amount_cumsum"] = ua.order_amount.cumsum()
ua["amount_sum"] = ua.order_amount.sum()
ua["prop"] = ua.apply(lambda x:x.amount_cumsum/x.amount_sum,axis=1 )
ua.prop.plot(figsize=(12,6))
可以看到,前20000的客户贡献了40%的消费,后面4000的客户贡献了60%的金额,呈现二八倾向。
9.计算用户生命周期
求出每个客户的最早和最晚的消费日期作差得到最早和最晚的时间间隔时长,即为客户的生命周期。
user_purchase = df[["user_id","order_product","order_amount","order_date"]]
order_date_min = user_purchase.groupby("user_id").order_date.min() #按客户分组求最早的消费日期
order_date_max = user_purchase.groupby("user_id").order_date.max() #按客户分组求最近的消费日期
(order_date_max-order_date_min).dt.days.hist(bins=40,figsize=(10,6))
大部分客户只消费了一次,开始时间和结束时间都是一样的所以相减为0,因此大部分客户集中在0。
剔除只消费1次的,对消费2次及以上的客户进行分析。
lft = (order_date_max-order_date_min).dt.days
lft[lft>0].hist(bins=100,figsize=(10,6))
消费2次及以上的客户生命周期呈现双峰趋势,处于左峰部分的客户生命周期在0至100天内,虽然消费了2次但没有能持性,因此在该部分客户首次消费30天后应该进行主动营销引导后续消费;处于右侧峰部分的客户生命周期集中在400天以后,属于忠诚用户;而集中在50-300天的属于普通型的生命周期。
--end--
5大系列图文,永久访问权限,内容节选参考👉《再见pandas》
长按扫码立即加入👇
👇点击阅读原文立即加入