电商平台用户消费行为分析

项目背景:

本项目数据来源于某电商平台消费记录,4个字段,共69659条记录.

  • user_id:用户ID
  • order_dt:购买日期
  • order_products:购买产品数
  • order_amount:购买金额

分析内容分为4个部分,


image.png

1.数据预处理

#数据导入与处理
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df=pd.read_csv(r"D:\桌面\单车案例\bicycle_master.txt",names=['user_id','order_date','order_product','order_amount'],sep='\s+')
df.info()
image.png

数据集没有空值

df.head()
image.png

订单时间数据类型需要转换

df['user_id']=df['user_id'].apply(str)
df['month']=pd.to_datetime(df['order_date']).apply(lambda x:x.strftime('%Y-%m'))
df.info()
df.head()
image.png
df.describe()
image.png

由上可知:
1.用户每个订单平均消费2.4个产品,大部分订单集中在小额
2.用户平均消费金额35.89,中位数在25.98,有一定的极值干扰。

2.用户消费趋势分析(按月)

  • 2.1每月消费总金额
grouped_month=df.groupby('month')
order_month_info=grouped_month.agg({'user_id':'count','order_product':'sum','order_amount':'sum'})
order_month_info['消费人数']=grouped_month.user_id.nunique()
order_month_info=order_month_info.rename(columns={'user_id':'消费次数','order_product':'购买量','order_amount':'消费金额'}).reset_index()
#绘图
plt.rcParams['font.sans-serif']='SimHei'
plt.rcParams['axes.unicode_minus']=False
plt.figure(figsize=(8,6))
plt.subplot(1,1,1)
x=order_month_info['month']
y1=order_month_info['消费金额']
plt.plot(x,y1,label="月消费金额")
plt.legend()
image.png

由图可知,月消费金额在1-3月呈上升趋势,3月达到顶峰,后期销量趋于平稳,每月在一万左右波动。

  • 2.2每月购买量
y2=order_month_info['购买量']
plt.figure(figsize=(8,6))
plt.plot(x,y2,label='月购买量')
plt.legend()
image.png

由上图可知,产品购买量在前三个月达到最高峰,后续消费较为稳定,有轻微下降趋势
-2.3每月消费人次和消费次数对比

y3=order_month_info['消费人数']
plt.figure(figsize=(8,6))
plt.plot(x,y3,label='月消费人数')
y4=order_month_info['消费次数']
plt.plot(x,y4,label='月消费次数')
plt.legend()
image.png

每月消费人数低于每月消费次数,但差异不大
前三个月每月的消费人数在8000-10000之间,后续月份,平均消费人数在2000不到

3用户个体消费分析

  • 3.1用户消费金额、购买数量描述统计
user=df.groupby('user_id')
user.sum().describe()
image.png

分析:
平均每位用户购买了7件商品,购买最多的有1033件;
用户平均消费金额为106元,与75分位接近,说明有少数人购买了大量的货物。

  • 用户消费金额与购买数量散点图
grouped_user_info=grouped_user.sum()
x=grouped_user_info['order_product']
y=grouped_user_info['order_amount']
plt.scatter(x,y)
plt.xlabel("购买数量")
plt.ylabel('购买金额')
image.png

由散点图可知,用户购买量与购买金额呈正相关关系。

  • 3.2用户消费金额分布
grouped_user_sum_order_amount=grouped_user_info.order_amount.reset_index()
grouped_user_sum_order_amount=grouped_user_sum_order_amount.loc[grouped_user_sum_order_amount['order_amount']<1400]
plt.hist(grouped_user_sum_order_amount.order_amount,bins=28,label='频次')
plt.legend(loc="upper right")
plt.show()
image.png

分析:
从直方图可知,大部分用户的消费能力确实不高,绝大部分集中在小于200元的消费档次。高消费用户在图上几乎看不到。

  • 用户购买件数分布
#3.3用户购买量分布
grouped_user_sum_order_product=grouped_user_info.order_product.reset_index()
grouped_user_sum_order_product=grouped_user_sum_order_product.loc[grouped_user_sum_order_product['order_product']<=100]
plt.hist(grouped_user_sum_order_product.order_product,bins=20,label='频次')
plt.legend(loc="upper right")
plt.show()
image.png

分析:绝大多数人购买件数小于5件

  • 用户消费占比分析
user_cumsum=grouped_user_info.sort_values('order_amount').apply(lambda x:x.cumsum()/x.sum())
user_cumsum_order_amount=user_cumsum.reset_index().order_amount.plot()
image.png

分析:
按用户消费金额进行升序排序,由图可知50%的用户仅贡献了15%的销售额。而排名前5000的用户就贡献了60%的消费额
也就是说,只要维护好这5000个客户,就可以完成业绩KPI的60%。

四.用户消费行为

image.png

4.1用户第一次购买

grouped_user_min=grouped_user.min().month.value_counts()
grouped_user_min
image.png

用户第一次购买集中在前3个月中

4.2用户最后一次购买

grouped_user_max=grouped_user.max().month.value_counts()
grouped_user_max.plot()
image.png

用户最后一次购买集中在前3个月中,说明很多用户购买过一次就不再购买,随着时间增加,最后一次购买用户数递增,说明用户流失呈上升状态,用户忠诚度下降。
-## 4.3新老客户消费比(多少用户只购买了一次,每月新客占比)

user_life=grouped_user.order_date.agg(['min','max'])
(user_life['min']==user_life['max']).value_counts()
image.png

分析可见:约有一半的人只购买了一次

  • 每月新客占比
#每月新客占比
grouped_new=df.groupby(['month','user_id']).order_date.agg(['max','min'])
grouped_new['new']=(grouped_new['min']==grouped_new['max'])
grouped_new=grouped_new.reset_index().groupby('month').new.value_counts()
grouped_new1=grouped_new.reset_index(name='计数')
grouped_new1['月用户量']=grouped_new1.groupby('month')['计数'].transform('sum')#transform的用法
grouped_new1=grouped_new1[(grouped_new1['new'])]
grouped_new1['新客占比']=grouped_new1['计数']/grouped_new1['月用户量']
x=grouped_new1['month']
y=grouped_new1['新客占比']
plt.plot(x,y,label='新客占比')
plt.legend()
plt.show()
image.png

分析:第1个月新客占比最高,并在接下来的三个内急剧下降,之后趋于稳定,在0.81左右波动。

4.4用户分层:RFM模型

# 用户分层
# 画 RFM,先对原始数据进行透视
rfm=df.pivot_table(index='user_id',
                  values=['order_product','order_amount','order_date'],
                  aggfunc={'order_date':'max',
                          'order_amount':'sum',
                          'order_product':'sum'})
rfm['R']= (rfm.order_date - rfm.order_date.max())/np.timedelta64(1,'D')
rfm.rename(columns={'order_product':"F",'order_amount':'M'},inplace=True)
rfm[['R','F','M']]=rfm[['R','F','M']].apply(lambda x:x-x.mean())
rfm[['R','F','M']].head()
image.png
# 根据RFM值给用户打标签
def rfm_func(x):
    level=x.apply(lambda x:'1' if x>=0 else '0')
    label=level.R + level.F + level.M
    d={
        # R 为1 表示比均值大,离最早时间近,F为1 表示 消费金额比较多,M 为1 表示消费频次比较多,所以是重要价值客户
        '111':'重要价值客户',
        '011':'重要保持客户',
        '101':'重要发展客户',
        '001':'重要挽留客户',
        '110':'一般价值客户',
        '010':'一般保持客户',
        '100':'一般发展客户',
        '000':'一般挽留客户',
    }
    result=d[label]
    return result
# 注意这里是要一行行的传递进来,所以 axis=1,传递一行得到一个 111,然后匹配返回一个值
rfm['label']=rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(rfm_func,axis=1)
rfm.loc[rfm.label=='重要价值客户','color']='g'
rfm.loc[~(rfm.label=='重要价值客户'),'color']='b'
rfm.plot.scatter('F','R',c=rfm.color)
image.png
rfm.groupby('label').count()
image.png
rfm.groupby('label').sum()
image.png

分析:
1.从RFM分层可知,大部分用户为一般挽留客户,但是这是由于极值的影响,所以RFM的划分应该尽量以业务为准。
尽量用小部分的用户覆盖大部分的额度,不能为了数据好看划分等级。

  • 新、活跃、回流、流失
pivoted_counts=df.pivot_table(index='user_id',
                             columns='month',
                             values='order_date',
                             aggfunc='count').fillna(0)
pivoted_counts.head()
image.png
# 转变一下消费,有消费为1,没有消费为0
df_purchase=pivoted_counts.applymap(lambda x:1 if x>0 else 0)
df_purchase.tail()
image.png
def active_status(data):
    status=[]
    # 数据一共有18个月份,每次输入一行数据,这样进行逐月判断
    for i in range(18):
        # 若本月没有消费,上面处理过的结果
        if data[i]==0:
            if len(status)>0:
                if status[i-1]=='unreg':
                    status.append('unreg')
                else:
                    status.append('unactive')
            else:
                # 之前一个数据都没有,就认为是未注册
                status.append('unreg')
                
        # 若本月消费
        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 status 
image.png
purchase_stats=df_purchase.apply(lambda x: pd.Series(active_status(x),index=df_purchase.columns),axis=1)
purchase_stats.head()
image.png

每月不同活跃数的计数

purchase_stats_ct=purchase_stats.apply(lambda x:pd.value_counts(x))
purchase_stats_ct
image.png
  • 每月不同活跃数占比
purchase_stats_ct_info = purchase_stats_ct.fillna(0).T
purchase_stats_ct_info.plot.area()
image.png
returnratee=purchase_stats_ct.T.apply(lambda x:x/x.sum(),axis=1)
returnratee

求环比值

#求每月环比
purchase_stats_ct_T=purchase_stats_ct.T
(purchase_stats_ct_T-purchase_stats_ct_T.shift())/purchase_stats_ct_T.shift()
image.png

image.png

4.5用户购买周期(按订单)

# 将用户分组后,计算相邻两个订单的时间间隔,shift 函数是对数据进行错位,所有数据会往下平移一下,所以可以
order_diff=grouped_user.apply(lambda x:x.order_date-x.order_date.shift())
order_diff.head(10)
image.png
order_diff.describe()
(order_diff/np.timedelta64(1,'D')).hist(bins=10)
image.png
image.png

分析:购买周期呈指数分布,平均购买周期68天,购买周期集中在100天以下。

4.6 用户生命周期

# 用户生命周期(按第一次和最后一次消费)
(user_life['max']-user_life['min']).describe()
image.png
user_life_info = ((user_life['max']-user_life['min'])/np.timedelta64(1,"D"))
user_life_info.plot.hist(bins=20)
image.png

分析:
1.用户的生命周期受只购买一次的用户影响比较厉害(可以排除)
2.用户平均生命周期134天,中位数仅0天
忽略只购买一次的用户

user_life['差值']=((user_life['max']-user_life['min'])/np.timedelta64(1,"D"))
user_life=user_life.loc[user_life['差值']!=0]
user_life['差值'].plot.hist()
plt.show()
image.png

分析:

  • 1.用户生命周期集中在400-500天左右

6.复购率和回购率

  • 复购率
    自然月内,购买多次的用户占比(即,购买了两次以上)
  • 回购率
    曾经购买过的用户在某一时期的再次购买的占比(可能是在三个月内)
    计算购买2次以上的用户(记为1,否则记为0)
purchase_r=pivoted_counts.applymap(lambda x: 1 if x>1 else np.NaN if x==0 else 0)
purchase_r.head()
image.png
purchase_r_reshop = (purchase_r.sum()/purchase_r.count()).reset_index(name = 'reshop')
purchase_r_reshop
image.png
plt.plot(purchase_r_reshop.month,purchase_r_reshop.reshop)
image.png

复购率稳定在20%左右,前一个月因为有大量新用户涌入,而这批用户只购买了一次,所以导致复购率降低

  • 回购率
# 回购率,知道是否消费就可以了
df_purchase.head()
image.png
# 需要使用函数来判断是否回购:当月消费过的用户下个月也消费了叫做回购,这个定义可以改变
def purchase_back(data):
    '''判断每一个月是否是回购,根据上个月是否购买来判断,上个月消费下个月没有购买就不是回购'''
    status=[]
    for i in range(17):
        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)
    # 第18个月补充NaN
    status.append(np.NaN)
    return status
indexs=df['month'].sort_values().astype('str').unique()
purchase_b = df_purchase.apply(lambda x :pd.Series(purchase_back(x),index = indexs),axis =1)
purchase_b.head()
image.png
purchase_b_backshop = purchase_b.sum()/purchase_b.count()
plt.figure(figsize=(8,6))
purchase_b_backshop.plot()
image.png

分析:
1.从上图看出,用户的回购率高于复购率,约在30%左右
2.从回购率和复购率综合分析,新客的整体质量低于老客
完毕

你可能感兴趣的:(电商平台用户消费行为分析)