[数据分析笔记] 用户消费行为分析

0.导入数据

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
columns = ['user_id', 'order_dt', 'order_products', 'order_amount']
df = pd.read_table('CDNOW_master.txt', names=columns, sep='\s+')
  • user_id: 用户ID
  • order_dt: 购买日期
  • order_products: 购买产品数
  • order_amount: 购买金额
df.head()

在这里插入图片描述

df.info()

在这里插入图片描述

df.describe()

在这里插入图片描述

  • 大部分订单只消费了少量商品(平均2.4),有一定极值干扰
  • 用户的消费金额比较稳定,平均消费35元,中位数在26元,有一定极值干扰
df['order_dt'] = pd.to_datetime(df.order_dt, format="%Y%m%d") # 解析日期
df['month'] = df.order_dt.values.astype('datetime64[M]') # 生成month变量
df.head()

在这里插入图片描述

1.进行用户消费趋势分析(按月)

  • 每月的消费总金额
  • 每月的消费次数
  • 每月的产品购买量
  • 每月的消费人数
grouped_month = df.groupby('month') # 按月聚合
order_month_amount = grouped_month.order_amount.sum() # 加总每月消费额
order_month_amount.head()

在这里插入图片描述

# 每月总金额折线图
order_month_amount.plot()

在这里插入图片描述
由上图可知,消费金额在前三个月达到最高峰,后续消费额较为稳定,有轻微下降趋势

# 每月消费订单数
grouped_month.user_id.count().plot()

在这里插入图片描述
前三个月消费订单数在10000笔左右,后续月份的平均消费人数在2500人左右

# 每月消费商品总数
grouped_month.order_products.sum().plot()

在这里插入图片描述

# 每月消费人数
# user_id 作为输入,去重
df.groupby('month').user_id.apply(lambda x:len(x.drop_duplicates())).plot()

在这里插入图片描述

# 另一种方法去重
(df.groupby(['month', 'user_id']).count().reset_index()).groupby('month').user_id.count().plot()

在这里插入图片描述

  • 每月消费人数低于每月消费次数,但差异不大
  • 前三个月每月的消费人数在8000-10000之间,后续月份,平均消费人数在2000人不到
# 使用数据透视表
df.pivot_table(index = 'month',
               values = ['order_products', 'order_amount', 'user_id'],
               aggfunc = {'order_products': 'sum',
                          'order_amount': 'sum',
                          'user_id': 'count'}).head()

在这里插入图片描述

2.用户个体消费

  • 用户消费金额、消费次数的描述统计
  • 用户消费金额和消费的散点图
  • 用户消费金额的分布图
  • 用户消费次数的分布图
  • 用户累计消费金额占比(百分之多少的用户占了百分之多少的消费额)
grouped_user = df.groupby('user_id')
grouped_user.sum().describe()

在这里插入图片描述

  • 用户平均购买了7张CD,但是中位值只有3,说明小部分用户购买了大量的CD
  • 用户平均消费106元,中位值有43,有极值干扰
grouped_user.sum().plot.scatter(x='order_amount', y='order_products')

在这里插入图片描述

# order_amount < 4000的数据
grouped_user.sum().query('order_amount < 4000').plot.scatter(x='order_amount', y='order_products')

在这里插入图片描述

# 消费金额分布
grouped_user.sum().order_amount.plot.hist(bins=20)

在这里插入图片描述
从直方图可知,用户消费金额,绝大部分呈现集中趋势,小部分异常值干扰了判断,可以使用过滤操作排除异常

# 购买产品数
grouped_user.sum().query('order_products < 100').order_products.hist(bins=20)

在这里插入图片描述
使用切比雪夫定理过滤异常值

user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum() / x.sum())
user_cumsum.head()

在这里插入图片描述

user_cumsum.tail()

在这里插入图片描述

user_cumsum.reset_index().order_amount.plot()

在这里插入图片描述

按用户消费金额进行升序排列,由图可知50%的用户仅贡献了15%的消费额度

3.用户消费行为

  • 用户第一次消费(首购)
  • 用户最后一次消费
  • 新老客消费比
    • 多少用户仅消费了一次
    • 每月新客占比
  • 用户分层
    • RFM
    • 新、老、活跃、回流、流失
  • 用户购买周期(按订单)
    • 用户消费周期描述
    • 用户消费周期分布
  • 用户生命周期(按第一次和最后一次消费)
    • 用户生命周期描述
    • 用户生命周期分布
grouped_user.min().order_dt.value_counts().plot()

在这里插入图片描述

  • 用户第一次购买分布集中在前三个月
  • 其中,在2月11日至2月25日有一次剧烈的波动
grouped_user.max().order_dt.value_counts().plot()

在这里插入图片描述

  • 用户最后一次购买的分布比第一次广
  • 大部分最后一次购买集中在前三个月,说明有很多用户购买了一次之后就不再进行购买
  • 随着时间的递增,最后一次购买数也在递增,消费呈现流失上升的状况
user_life = grouped_user.order_dt.agg(['min', 'max'])
user_life.head()

在这里插入图片描述

(user_life['min'] == user_life['max']).value_counts()

在这里插入图片描述
有一半用户只消费了一次

rfm = df.pivot_table(index = 'user_id',
               values = ['order_products', 'order_amount', 'order_dt'],
               aggfunc = {'order_dt': 'max',
                          'order_amount': 'sum',
                          'order_products': 'sum'})
rfm.head()

在这里插入图片描述

# 距今天数 转换时间格式 把单位消除
rfm['R'] = -(rfm.order_dt - rfm.order_dt.max()) / np.timedelta64(1, 'D')
# 重命名
rfm.rename(columns= {'order_products': 'F', 'order_amount': 'M'}, inplace=True)
rfm.head()

在这里插入图片描述

rfm[['R', 'F', 'M']].apply(lambda x:x-x.mean()).head() # 负号表示小于平均值

在这里插入图片描述

def rfm_func(x):
    level = x.apply(lambda x:'1' if x>=0 else '0') # x大于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)
rfm.head()

在这里插入图片描述

rfm.groupby('label').sum()

在这里插入图片描述

rfm.loc[rfm.label == '重要价值客户', 'color'] = 'coral'
rfm.loc[~(rfm.label == '重要价值客户'), 'color'] = 'c' # 除了重要价值客户之外的客户
rfm.plot.scatter('F', 'R', c=rfm.color)

在这里插入图片描述

rfm.head()

在这里插入图片描述
从RFM分层可知,大部分用户为重要保持客户,但是这是由于极值的影响,所以RFM的划分标准

  • 尽量用小部分的用户覆盖大部分的额度
  • 不要为了数据好看划分等级
pivoted_counts = df.pivot_table(index = 'user_id',
                                columns = 'month',
                                values = 'order_dt',
                                aggfunc = 'count').fillna(0)
pivoted_counts.head()

在这里插入图片描述

df_purchase = pivoted_counts.applymap(lambda x: 1 if x > 0 else 0)
df_purchase.tail()

在这里插入图片描述

def active_status(data):
    status = []
    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 pd.Series(status)

若本月没有消费

  • 若之前未注册,则依旧为未注册
  • 若之前有消费,则为流失/不活跃
  • 其他情况,为未注册

若本月有消费

  • 若是第一次消费,则为新用户
  • 若之前有过消费,上个月为不活跃,则为回流
  • 若上个月为未注册,则为新用户
  • 除此之外,为活跃
print(df_purchase.columns)

在这里插入图片描述

purchase_stats = df_purchase.apply(active_status, axis=1)
purchase_stats.columns = df_purchase.columns
purchase_stats.head()

在这里插入图片描述

purchase_stats.tail()

在这里插入图片描述

purchase_stats_ct = purchase_stats.replace('unreg', np.NaN).apply(lambda x:pd.value_counts(x))
purchase_stats_ct.head()

在这里插入图片描述

purchase_stats_ct.fillna(0).T.head()

在这里插入图片描述

purchase_stats_ct.fillna(0).T.apply(lambda x:x/x.sum(), axis=1)

在这里插入图片描述

purchase_stats_ct.fillna(0).T.plot.area()

在这里插入图片描述

order_diff = grouped_user.apply(lambda x:x.order_dt - x.order_dt.shift())
order_diff.head(10)

在这里插入图片描述

df.order_dt.head(10)

在这里插入图片描述

df.order_dt.shift().head(10) # 把所有数据往下移动一位

在这里插入图片描述

order_diff.describe()

在这里插入图片描述

(order_diff / np.timedelta64(1, 'D')).hist(bins=20)

在这里插入图片描述

  • 订单周期呈指数分布
  • 用户的平均购买周期是68天
  • 绝大部分用户的购买周期都低于100天
(user_life['max'] - user_life['min']).describe()

在这里插入图片描述

((user_life['max'] - user_life['min']) / np.timedelta64(1, 'D')).hist(bins= 40)

在这里插入图片描述
用户的生命周期受只购买一次的用户影响比较厉害

u_1 = ((user_life['max'] - user_life['min']).reset_index()[0] / np.timedelta64(1, 'D'))
u_1[u_1 > 0].hist(bins = 40)

在这里插入图片描述

4.复购率和回购率分析

  • 复购率
    • 自然月内,购买多次的用户占比
  • 回购率
    • 曾经购买过的用户在某一时期内的再次购买的占比
pivoted_counts.head()

在这里插入图片描述

# 大于1 -> 1
# 等于1 -> 0
# 等于0 -> NaN
purchase_r = pivoted_counts.applymap(lambda x: 1 if x > 1 else np.NaN if x == 0 else 0)
purchase_r.head()

在这里插入图片描述

(purchase_r.sum() / purchase_r.count()).plot(figsize=(10, 4))

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

df_purchase.head()

在这里插入图片描述

# 1 -> 当月消费过,次月依旧消费
# 0 -> 当月消费过,次月没有消费
# NaN -> 当月没有消费
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)
    status.append(np.NaN)
    return pd.Series(status)
purchase_b = df_purchase.apply(purchase_back, axis=1)
purchase_b.head(5)

在这里插入图片描述

(purchase_b.sum() / purchase_b.count()).plot(figsize=(10, 4))

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值