赞
踩
用户行为贯穿我们生活的各行各业,通过分析用户的消费行为,可以帮助企业更好的了解企业发展状况,及时做出战略调整,使企业更好的运转下去。本文以某电商网页用户购买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月份加大了促销力度,使前三个月商品的销售数量、金额、用户消费次数上升。但是消费人数从二月份就开始下降,猜测可能是商品的使用体验感较好,使部分新客转化为老客。
user_grouped=df.groupby(by='user_id').sum()
print(user_grouped.describe())
结论:
① 用户角度:用户数量23570人,每个用户平均购买7个产品,但是中位数为3,最大购买数量为1033,平均值大于中位数,属于典型的右偏分布
② 消费金额角度:用户平均消费106,中位数43,存在土豪用户消费13990,结合分位数和最大值来看,平均数与75%分位数几乎相等,属于右偏分布
上图为每个用户购买产品的数量与消费金额的散点图,从图中可知,用户的消费金额与购买数量呈现线性趋势,每个商品均价15左右,订单的极值点比较少(消费金额>1000,或者购买数量>60),对于样本来说影响不大,可以忽略不计
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的用户占据大多数
# 每个用户的消费金额
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原则)
df.groupby(by='user_id')['order_date'].min().value_counts().plot()
plt.savefig('figs/savefig5.png')
plt.show()
结论:从图中可以看出,用户第一次购买CD的时间集中在四月份前,猜测1到4月份公司加大了促销力度,吸引来很多新用户。整体来看,在2月份前新客呈上升趋势,2月份后呈现下降趋势,猜测是公司的推广力度或者价格调整所致。
df.groupby(by='user_id')['order_date'].max().value_counts().plot()
plt.savefig('figs/savefig5.png')
plt.show()
结论:大多数用户最后一次购买时间集中在前3个月,忠诚用户较少;3月中旬最后一次购买商品的用户数量急剧下降,但随着时间推移,最后一次购买商品的用户数量再次呈现上升趋势。猜测这份数据选择的是前3个月消费用户在后面18个月的跟踪记录
构建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 result rfm['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名重要保持用户,应制定一些策略,提升一般用户转化成重要用户的转化率
定义:
将第一次消费的客户定义为新用户
活跃用户即老客,在某一个时间窗口内有过消费
不活跃用户则是时间窗口内没有消费过的老客
回流用户:相当于回头客的意思,可以分为自主回流和人工回流,自主回流指顾客自己回流了,而人工回流则是人为参与导致的
处理数据:将用户分为:新用户、活跃用户、不活跃用户、回流用户和未消费用户
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%左右
③ 网站运营稳定后,回流用户占比大于活跃用户
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天左右进行电话回访,通过赠送优惠券等活动,增大消费频率
计算方式:用户最后一次购买日期 - 第一次购买日期,如果差值=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天,属于忠诚客户,需要大力维护此类用户。
复购率计算方式:在自然月内,购买多次的用户在总消费人数中的占比
# 自然月内复购用户用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左右
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。