用户消费行为分析
- 前言
- 一、数据预处理
- 二、用户整体消费趋势分析(按月份)
- 三、用户的个体消费分析
- 1 用户消费金额、消费次数(产品数量)描述统计
- 2 用户消费分布分析
- 3 用户累计消费金额占比分析(用户的贡献度)
- 四、用户消费行为分析
- 1 首购时间分析
- 2 最后一次购买时间分析
- 3 用户分层
- 4 新客、活跃用户、回流用户分析
- 5 用户的购买周期
- 6 用户的生命周期
- 7 用户的复购率和回购率
- 五、 总结
前言
用户行为贯穿我们生活的各行各业,通过分析用户的消费行为,可以帮助企业更好的了解企业发展状况,及时做出战略调整,使企业更好的运转下去。本文以某电商网页用户购买CD数量明细作为样本数据,整理了分析用户消费行为的具体内容。
一、数据预处理
本文分析的数据为文本类型的数据,没有列名,为了方便后续分析,需要为此数据添加列头,代码如下:
columns=['user_id','order_dt','order_products','order_amount']
df=pd.read_table('CDNOW_master.txt',names=columns,sep='\s+')
数据具体信息如下:
观察该数据可以发现:① 该数据数据量较大,但数据很完整,不存在缺失值;② 日期为int类型,需要转换格式;③ 存在同一个用户一天内购买多次的行为;④ 用户平均每笔订单购买2~3个商品,标准差为2.3,波动不大,用户购买数量的75%分位数处的值为3,说明绝大多数订单的购买量都不多;⑤ 购买金额反映出大部分订单消费金额集中在中小额,平均在35左右。
由上述观察得出的结论,对数据日期做如下调整:
首先转换日期格式,放入‘order_date"列中,代码如下:
df['order_date']=pd.to_datetime(df['order_dt'],format='%Y%m%d')
为了方便后面按月分析数据,添加新列“month",存放精度为月份的日期,代码如下:
df['month']=df['order_date'].values.astype('datetime64[M]')
修改后的数据如下:
二、用户整体消费趋势分析(按月份)
分别按月份统计产品购买数量、消费金额、消费次数、消费人数,具体代码如下:
plt.figure(figsize=(20,15)) # 单位是英寸
plt.subplot(221) # 绘子图 两行两列,占据第一个位置
# 每月的购买数量
df.groupby(by='month')['order_products'].sum().plot() # 默认折线图
plt.title('每月的购买数量')
# 每月的消费金额
plt.subplot(222)
df.groupby(by='month')['order_amount'].sum().plot()
plt.title('每月的消费金额')
# 每月的消费次数
plt.subplot(223)
df.groupby(by='month')['user_id'].count().plot()
plt.title('每月的消费次数')
# 每月的消费人数
plt.subplot(224)
df.groupby(by='month')['user_id'].apply(lambda x:len(x.drop_duplicates())).plot()
plt.title('每月的消费人数')
plt.show()
分析:
① 从图一、图二和图三可能看出,用户每月购买商品的数量、消费的金额、每个用户进店消费次数,在1月-3月都呈现上升的趋势,3月~4月急剧下降,随后波动至平稳。
② 每月进店消费的人数,在1到2月呈现上升的趋势,随后急剧下降至平稳状态。具体来说,前三个月消费人数在8000~10000左右,后续平均消费人数在2000左右。
③ 原因分析:1,2,3月份处于春节前后,消费者需求量增加;公司可能在1,2,3月份加大了促销力度,使前三个月商品的销售数量、金额、用户消费次数上升。但是消费人数从二月份就开始下降,猜测可能是商品的使用体验感较好,使部分新客转化为老客。
三、用户的个体消费分析
1 用户消费金额、消费次数(产品数量)描述统计
user_grouped=df.groupby(by='user_id').sum()
print(user_grouped.describe())
结论:
① 用户角度:用户数量23570人,每个用户平均购买7个产品,但是中位数为3,最大购买数量为1033,平均值大于中位数,属于典型的右偏分布
② 消费金额角度:用户平均消费106,中位数43,存在土豪用户消费13990,结合分位数和最大值来看,平均数与75%分位数几乎相等,属于右偏分布
上图为每个用户购买产品的数量与消费金额的散点图,从图中可知,用户的消费金额与购买数量呈现线性趋势,每个商品均价15左右,订单的极值点比较少(消费金额>1000,或者购买数量>60),对于样本来说影响不大,可以忽略不计
2 用户消费分布分析
plt.figure(figsize=(12,4))
plt.subplot(121)
plt.xlabel('每个订单的消费金额') # y轴为某个消费金额出现的次数
df['order_amount'].plot(kind='hist',bins=50) # bins:区间划分的次数,影响柱子的宽度
plt.subplot(122)
plt.xlabel('每个用户购买产品的数量')
df.groupby(by='user_id')['order_products'].sum().plot(kind='hist',bins=50)
plt.show()
结论:从图中看出,消费金额在100以内的订单占据了绝大多数,用户的购买数量较小,集中在50以内。总的来说,消费金额低、购买数量小于50的用户占据大多数
3 用户累计消费金额占比分析(用户的贡献度)
# 每个用户的消费金额
user_cumsum=df.groupby(by='user_id')['order_amount'].sum().sort_values().reset_index()
# 每个用户消费金额累加
user_cumsum['amount_cumsum']=user_cumsum['order_amount'].cumsum()
amount_cumsum=user_cumsum['amount_cumsum'].max()
# 前xx名用户的累计贡献率
# user_cumsum['prop']=user_cumsum['amount_cumsum']/amount_cumsum # 方法一
# user_cumsum['prop']=user_cumsum['amount_cumsum'].apply(lambda x:x/amount_cumsum) # 方法二
user_cumsum['prop']=user_cumsum.apply(lambda x:x['amount_cumsum']/amount_cumsum,axis=1) # 方法三
print(user_cumsum.tail()) # 取最后5行
user_cumsum['prop'].plot()
plt.savefig('figs/savefig4.png')
plt.show()
结论:前20000名用户贡献总金额的40%,剩余3500名用户贡献了60%(2/8原则)
四、用户消费行为分析
1 首购时间分析
df.groupby(by='user_id')['order_date'].min().value_counts().plot()
plt.savefig('figs/savefig5.png')
plt.show()
结论:从图中可以看出,用户第一次购买CD的时间集中在四月份前,猜测1到4月份公司加大了促销力度,吸引来很多新用户。整体来看,在2月份前新客呈上升趋势,2月份后呈现下降趋势,猜测是公司的推广力度或者价格调整所致。
2 最后一次购买时间分析
df.groupby(by='user_id')['order_date'].max().value_counts().plot()
plt.savefig('figs/savefig5.png')
plt.show()
结论:大多数用户最后一次购买时间集中在前3个月,忠诚用户较少;3月中旬最后一次购买商品的用户数量急剧下降,但随着时间推移,最后一次购买商品的用户数量再次呈现上升趋势。猜测这份数据选择的是前3个月消费用户在后面18个月的跟踪记录
3 用户分层
构建RFM模型:R代表最近购买日期,F表示购买次数(频率),M为购买金额
# 构建数据透视表
rfm=df.pivot_table(index='user_id',values=['order_products','order_amount','order_date'],aggfunc={'order_date':'max','order_products':'sum','order_amount':'sum'})
rfm['R']=(rfm['order_date'].max()-rfm['order_date'])/np.timedelta64(1,'D') # 取相差的天数,保留一位小数,值越小越好
rfm.rename(columns={'order_amount':'M','order_products':'F'},inplace=True)# RFM计算方式:每一列数据减去数据所在列的平均值,有正有负,与1作比较,大于置为1,小于1置为0
def rfm_func(x):level=x.apply(lambda x:'1' if x>=1 else '0')label=level['R']+level['F']+level['M']d={'111':'重要价值客户','011':'重要保持客户','101':'重要发展客户','001':'重要挽留客户','110':'一般价值客户','010':'一般保持客户','100':'一般发展客户','000':'一般挽留客户',}result=d[label]return resultrfm['label']=rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
print(rfm.head())
通过RFM模型将客户分为:重要价值客户、重要保持客户、重要发展客户、重要挽留客户、一般价值客户、一般保持客户、一般发展客户、一般挽留客户。
用户分层可视化
for label,grouped in rfm.groupby('label'):x=grouped['R']y=grouped['F']plt.scatter(x,y,label=label)
plt.legend() # 显示图例
plt.xlabel('R')
plt.ylabel('F')
plt.savefig('figs/savefig7.png')
plt.show()
rfm.groupby('label').size().plot()
plt.xticks(rotation=45)
plt.tight_layout() # 防止X轴标签显示不全
结论:一般用户占据绝大部分,23570名用户中只有4000名重要保持用户,应制定一些策略,提升一般用户转化成重要用户的转化率
4 新客、活跃用户、回流用户分析
定义:
将第一次消费的客户定义为新用户
活跃用户即老客,在某一个时间窗口内有过消费
不活跃用户则是时间窗口内没有消费过的老客
回流用户:相当于回头客的意思,可以分为自主回流和人工回流,自主回流指顾客自己回流了,而人工回流则是人为参与导致的
处理数据:将用户分为:新用户、活跃用户、不活跃用户、回流用户和未消费用户
pivoted_counts=df.pivot_table(index='user_id',columns='month',values='order_dt',aggfunc='count').fillna(0) # 将nan填充为0# 由于浮点数不直观,将其转换成是否消费,用 0、1表示
df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)# 判断是否是新用户、活跃用户、不活跃用户、回流用户
def active_status(data):status=[]for i in range(18): # 共有18列,即18个月if data[i]==0:if len(status)==0:status.append('unreg')else:if status[i - 1] == 'unreg':status.append('unreg')else:status.append('unactive')else:if len(status) == 0:status.append('new')else:if status[i - 1] == 'unactive':status.append('return')elif status[i - 1] == 'unreg':status.append('new')else:status.append('active')return pd.Series(status,df_purchase.columns)purchase_status=df_purchase.apply(active_status,axis=1)
print(purchase_status.head())
分析每种用户数量
# 用nan代替unreg
purchase_status_ct=purchase_status.replace('unreg',np.NaN).apply(lambda x:pd.value_counts(x))
purchase_status_ct.T.fillna(0).plot.area()
plt.savefig('figs/savefig8.png')
plt.show()
结论:前三个月,红色活跃用户和蓝色新用户,占比较大;四月份过后,新用户和活跃用户开始下降,并且呈现稳定趋势;回流用户主要产生再4月份后,呈现稳定趋势,是产品的重要客户。
回流用户和活跃用户分析
rate=purchase_status_ct.T.fillna(0).apply(lambda x:x/x.sum(),axis=1)
# 回流用户占比
plt.plot(rate['return'],label='return')
# 活跃用户占比
plt.plot(rate['active'],label='active')
plt.legend()
plt.savefig('figs/savefig9.png')
plt.show()
结论:
① 回流用户:前六个月,回流用户上涨,过后呈现下降趋势,平均维持在5%
② 活跃用户:前四个月活跃用户大量增长,猜测由于活动吸引来很多新用户导致,四月份过后开始下降,平均维持在2.5%左右
③ 网站运营稳定后,回流用户占比大于活跃用户
5 用户的购买周期
order_diff=df.groupby(by='user_id').apply(lambda x:x['order_date']-x['order_date'].shift()) # 当前订单日期-上一次订单日期
print(order_diff.head())
print(order_diff.describe())
(order_diff/np.timedelta64(1,'D')).hist(bins=20)
plt.savefig('figs/savefig10.png')
plt.show()
结论:由图可知,平均消费周期为68天,大多数用户消费周期低于100天,呈现典型的长尾分布,只有小部分用户消费周期在200天以上(不积极消费的用户)
建议:针对不积极消费用户,可在其消费3天左右进行电话回访,通过赠送优惠券等活动,增大消费频率
6 用户的生命周期
计算方式:用户最后一次购买日期 - 第一次购买日期,如果差值=0,说明用户仅仅购买了一次
user_life=df.groupby(by='user_id')['order_date'].agg(['min','max'])
(user_life['max']==user_life['min']).value_counts().plot.pie(autopct='%1.1f%%') # 格式化成1位小数
plt.legend(['仅消费一次','多次消费'])
plt.savefig('figs/savefig11.png')
plt.show()
结论:一半以上的用户仅仅消费了一次,说明运营不利,留存率不好
print((user_life['max']-user_life['min']).describe()) # 生命周期分析
结论:用户平均生命周期为134天,但是中位数=0,再次验证大多数用户消费了一次,低质量用户很多。75%分位数以后的用户,生命周期大于294天,属于核心用户,需要着重维护
绘制所有用户生命周期直方图 + 多次消费
plt.figure(figsize=(12,6))
plt.subplot(121)
((user_life['max']-user_life['min'])/np.timedelta64(1,'D')).hist(bins=15)
plt.title('所有用户生命周期')
plt.xlabel('生命周期天数')
plt.ylabel('用户量')
plt.subplot(122)
u_l = (user_life['max']-user_life['min']).reset_index()[0]/np.timedelta64(1,'D')
u_l[u_l>0].hist(bins=15)
plt.title('多次消费用户生命周期')
plt.xlabel('生命周期天数')
plt.ylabel('用户量')
plt.savefig('figs/savefig12.png')
plt.show()
结论:
① 对比可知,第二幅图过滤掉了生命周期=0的用户,呈现双峰结构。
② 图2中还有一部分用户的生命周期趋于0,虽然进行了多次消费,但是不能长期消费 ,属于普通用户,可针对性进行营销推广活动。
③ 少部分用户生命周期集中在300~500天,属于忠诚客户,需要大力维护此类用户。
7 用户的复购率和回购率
复购率计算方式:在自然月内,购买多次的用户在总消费人数中的占比
# 自然月内复购用户用1表示,非复购用户用0表示,没有消费记录的用户用Nan表示
purchase_r=pivoted_counts.applymap(lambda x:1 if x>1 else np.NaN if x==0 else 0)
# nan数值不参与count计数
(purchase_r.sum()/purchase_r.count()).plot(figsize=(12,6)) # purchase_r.sum():复购用户人数 purchase_r.count():总的消费人数
plt.savefig('figs/savefig13.png')
plt.show()
结论:前三个月复购率开始上升,后续趋于平稳维持在20%~22%之间。前三个月复购率较低可能是因为大批新用户仅仅购买一次造成的
回购率计算方式:在一个时间窗口内进行了消费,在下一个窗口内又进行了消费
# 由于浮点数不直观,将其转换成是否消费,用 0、1表示
df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
def purchase_back(data):status=[]for i in range(17):if data[i]==1: # 当前月份消费了if data[i+1]==1:status.append(1) # 回购用户else:status.append(0)else: # 当前月份没有消费status.append(np.NaN)status.append(np.NaN) # 填充最后一列数据return pd.Series(status,df_purchase.columns)purchase_b=df_purchase.apply(purchase_back,axis=1)# 回购率可视化
plt.figure(figsize=(20,4))
plt.subplot(211)
# 回购率,nan不参与count计算
(purchase_b.sum()/purchase_b.count()).plot(label='回购率')
# 复购率
purchase_r=pivoted_counts.applymap(lambda x:1 if x>1 else np.NaN if x==0 else 0)
(purchase_r.sum()/purchase_r.count()).plot(label='复购率')
plt.ylabel('百分比%')
plt.title('用户回购率和复购率对比图')# 回购人数与购物总人数
plt.subplot(212)
plt.plot(purchase_b.sum(),label='回购人数')
plt.plot(purchase_b.count(),label='购物总人数')
plt.title('回购人数与购物总人数')
plt.ylabel('人数')
plt.xlabel('month')
plt.legend()
plt.savefig('figs/savefig15.png')
plt.show()
结论:
① 由回购率可知,平稳后在30%左右,波动性稍微较大
② 复购率低于回购率,平稳后在20%左右,波动性较小
③ 前三个月不管是回购还是复购,都呈现上升趋势,说明新用户需要一定时间来变成复购或者回购用户
④ 结合新老客户分析,新客户忠诚度远低于老客户忠诚度
⑤ 前三个月购物总人数远远大于回购人数,三个月后,回购人数和购物总数开始稳定,回购人数稳定在1000左右,购物总人数在2000左右
五、 总结
- 整体趋势:每年的月份为单位分析,销量和销售额在1-3月份相对极高,然后骤降,原因可能跟这段时间的大力促销或与商品的季度属性有关。
- 用户个体特征:每笔订单的金额和商品购买量都集中在区间的低段水平,都是小金额小批量进行购买,此类交易群体,可在丰富产品线和增加促销活动提高转换率和购买率。
- 大部分用户的消费总额和购买总量都集中刚在低段,长尾分布,这个跟用户需求有关,可以对商品进行多元文化价值的赋予,增强其社交价属性,提高用户的价值需求。
- 用户的消费周期:有二次以上消费的用户,平均68天,所以在50天到60天期间,应该对这批用户进行刺激召回,细致点,比如10天回复满意度,30天发放优惠券,55天的时候提醒优惠券的使用。
- 用户的生命周期:有二次及以上消费的用户的平均生命周期是276天。用户的生命周期分别在20天内与400至500天间,应该在20天内对客户进行引导,促进其再次消费并形成消费习惯,延长其生命周期;在100至400天的用户,也要根据其特点推出有针对性的营销活动,引导其持续消费。
- 新客户的复购率约为12%,老客户的复购率在20%左右;新客户的回购率在15%左右,老客户的回购率在30%左右,需要营销策略积极引导其再次消费及持续消费。
- 用户质量:用户个体消费有一定规律性,大部分用户的消费集中在20O0以下,用户消费反应了2/8法则,消费排名前20%的用户贡献了80%的消费额。所以说,狠抓高质量用户是万古不变的道理,这些高质量客户都是“会员”类型,需要专门为会员优化购物体验,比如专线接听,特殊优惠等等。