该项目主要对某平台用户消费行为进行画像分析,通过pandas的灵活使用,对月销量、客户复购率、回购率、客户分层、高质量客户、留存率、消费间隔等进行多维度分析。以下为部分节选内容,完整数据和代码可在文末扫码了解👇
首先,加载用户的消费数据。
columns=["user_id","order_dt","order_product","order_amount"]
df = pd.read_csv('data.txt', sep='\s+', names=columns)
使用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)
)
(
df.groupby("order_month")['order_amount'].sum()
.plot(figsize=(10,6),marker='o')
)
一笔订单对应的总金额分布
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")
)
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()
反映出大部分人的消费额和购买数量都是较低,符合一般消费规律。
复购率定义:在一个月内消费次数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')
回购率:本月消费并在下月继续消费的客户占比
这里的定义是在一个月之内只要消费次数大于1即可认为是消费。
步骤:
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是由于没有下一期数据,可以视为异常忽略。
根据客户的活跃程度可将客户分为沉默户、新户、活跃户、不活跃户、回流用户,具体定义如下:
为了给每个客户在各观察月打上客户分层标签,需要借助一些辅助列。通过分组内偏移、排序、累计求和等方法实现。分组内的各种骚操作可以了解东哥的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))
按客户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%的金额,呈现二八倾向。
求出每个客户的最早和最晚的消费日期作差得到最早和最晚的时间间隔时长,即为客户的生命周期。
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--