数据蛙强化课程第一期

CD 网站上客户消费记录分析

2019-04-03  本文已影响0人  此我非彼我隆隆

1 项目介绍

分析步骤及内容:

  • 1. 数据预处理——数据的清洗
    缺失值的处理、数据类型的转化
  • 2. 用户消费趋势的分析
    从每月的消费总金额、每月的消费次数、每月的产品购买量、每月的消费人数四个维度上进行分析
  • 3. 用户个体消费数据分析
    用直方图,散点图分析累计消费
  • 4. 用户消费行为分析
    首购,用户分层,购买周期等分析

2 项目开始

2.1 数据预处理——清洗

# 导入必备库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
%matplotlib inline    #‘%’内置的命令,jupyter专有的定义,比如在pycharm不常用到,inline意思是我做好图之后可以在html页面的单元格进行显示
# 插入数据文件
columns = ['user_id', 'order_dt', 'order_products', 'order_amount']
df = pd.read_table('CDNOW_master.txt', names = columns, sep = "\s+")

注意4点

image.png
image.png
df['order_dt'] = pd.to_datetime(df.order_dt, format = '%Y%m%d') # Y表示四位数的日期部分,y表示两位数的日期部分
df['month'] = df.order_dt.values.astype('datetime64[M]') # 增加一个 month 字段,转变时间维度便于分析
image.png
image.png
image.png

小结:至此,已完成数据的清洗

2.2 进行用户消费趋势的分析(按月)

2.2.1 每月消费总金额

grouped_month = df.groupby('month')  # 按月进行聚合数据,形成新的对象
order_month_amount = grouped_month.order_amount.sum()  # 求出订货量的总数
order_month_amount.head()
image.png image.png

2.2.3 每月产品购买量

grouped_month.order_products.sum().plot()  # 每笔订单可能会有多个产品,可求出总产品的销售量
image.png

2.2.4 每月消费人数(需要去重)

2.3 用户个体消费分析

2.3.1 用户消费金额和消费次数的描述统计

grouped_user = df.groupby('user_id')
grouped_user.sum().describe()
image.png

2.3.2 用户消费金额和消费次数的散点图和直方图

grouped_user.sum().query('order_amount < 4000').plot.scatter(x = 'order_amount', y = 'order_products')
image.png
grouped_user.sum().query('order_products < 60').order_products.hist(bins = 40)  #
image.png

2.3.3 用户累计消费金额的占比

理解:

user_cumsum = grouped_user.sum().sort_values('order_amount').cumsum() / 2500315.63   # cumsum 为滚动累加求和
user_cumsum
image.png
user_cumsum = grouped_user.sum().sort_values('order_amount').apply(lambda x:x.cumsum() / x.sum())
user_cumsum  # apply(lambda x:x.cumsum() / x.sum()),除数为占比,被除数为总数
image.png
user_cumsum.reset_index().order_amount.plot()  # user_cumsum 其实是一个series,reset_index 会把其转换为数据框,这样便于制图
                                               # order_amount 也可用 order_products 代替,可得出几乎一样的结果
image.png

结论: - 前 2 万用户消费占比 0.4,后5千用户占比 0.6
- 重点维系对象应放在这5千人上

2.4 用户消费行为分析

  1. 用户第一次消费(首购)
    在很多行业里面首购是一个很重要的维度,它和渠道息息相关,尤其是针对客单价比
    较高客户留存率比价低的行业,第一次客户从哪里来可以拓展出很多运营方式。
    用户最后一次消费
  2. 新老客消费比
    • 多少用户仅消费了一次
    • 每月新客占比
  3. 用户分层
    • RFM
    • 新、老、活跃、流失
  4. 用户购买周期(按订单)
    • 用户消费周期描述
    • 用户消费周期分布
  5. 用户生命周期(按第一次&最后一次消费)
    • 用户生命周期描述
    • 用户生命周期分布
image.png image.png image.png

2.4.2 新老客户消费比

从两个维度分析

user_life = grouped_user.order_dt.agg(['min', 'max'])  # 定义用户的购买周期
user_life.head()
image.png image.png

2.4.3 用户分层

2.4.3.1 RFM

rfm = df.pivot_table(index = 'user_id',
                     values = ['order_products', 'order_amount', 'order_dt'],  # 3 个字段,购买日期,购买金额,购买产品
                     aggfunc = {'order_dt':'max',
                                'order_amount':'sum',
                                'order_products':'sum'})  # 这里所求的是消费产品数,这样可以更加详细的区分
rfm.head()
image.png
rfm['R'] = -(rfm.order_dt - rfm.order_dt.max()) / np.timedelta64(1, 'D')  # 客户最近一次购买日期减去今天(98年6月底)算出时间间距,
                                                                          # 由于时间类型是日期型,所以要转换为浮点数,除以天数去掉单位
rfm.rename(columns = {'order_products':'F', 'order_amount':'M'},inplace =True)  # 统一下字段名
rfm.head()
image.png
rfm[['R','F','M']].apply(lambda x : x - x.mean()).head()  # 每个客户在 R F M 三个维度上的值与平均值之差
image.png
def rfm_func(x):
    level = x.apply(lambda x:'1' if x >= 1 else '0')
    label = level.R + level.F + level.M  # 拼接为其中一种组合
    d = {                                # R F M 三个维度可以显示出一个客户的价值,三个维度可以细分为8种组合
        '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()
image.png
image.png
rfm.loc[rfm.label == '重要价值客户', 'color'] = 'g'  # 后来赋予的颜色
rfm.loc[~(rfm.label == '重要价值客户'), 'color'] = 'r' # 后来赋予的颜色
rfm.plot.scatter('F', 'R', c = rfm.color)  # 不能直接赋予颜色,必须先赋值
image.png
image.png

2.4.3.2 新、活跃、回流、流失和不活跃用户

1. 可以先用数据透视表查看用户每月购买次数

pivoted_counts = df.pivot_table(index = 'user_id',
                                columns = 'month',
                                values = 'order_dt',
                                aggfunc = 'count').fillna(0)  # 没有消费的会用 0 进行填充
pivoted_counts.head()
image.png
2. 简化模型(因为每月用户购买次数并不是重要数据,是否购买才是重点)
image.png
def active_status(data):
    status = []   
    for i in range(18):  # 遍历 18 个月的消费情况
        
        # 若本月没有消费
        if data[i] == 0:  # 判断是否为 0, 0 表示没有消费
            if len(status) > 0:  # 遍历18个月的情况后,如果其中一个月有消费,则长度大于 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


indexs = df['month'].sort_values().astype('str').unique()
pivoted_purchase_status = pivoted_counts.apply(lambda x:pd.Series(active_status(x),index = indexs),axis=1)
image.png
purchase_status_ct = pivoted_purchase_status.replace('unreg',np.NaN).apply(lambda x : pd.value_counts(x))
purchase_status_ct
image.png image.png image.png image.png

2.4.4 用户购买周期

order_diff = grouped_user.apply(lambda x : x.order_dt - x.order_dt.shift())  # shift() 错位函数使数据依次向下移位,第一个值则会变为空值
order_diff.head(10)
image.png image.png image.png image.png

结论:
1. 订单周期呈指数分布
2. 用户的平均购买周期是68天
3. 绝大部分用户的购买周期都低于100天

2.4.5 用户生命周期

image.png
image.png image.png

2.5 复购率和回购率的分析

def purchase_back(data):  # 定义一个回购函数 
    status = []
    for i in range(17):  # 从第一个月开始遍历
        if data[i] == 1:  # 判断某一个月(从第一个月算起)是否有消费,如果有则分为下面两种情况
            if data[i + 1] == 1:  
                status.append(1)  # 判断后一个月是否有消费,如果有则用 1 表示
            if data[i + 1] == 0:
                status.append(0)  # 判断后一个月是否有消费,如果没有则用 0 表示
        else:
            status.append(np.NaN)  # 如果第一个月(前一个月)没有消费则用 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(5)
image.png image.png
上一篇 下一篇

猜你喜欢

热点阅读