机器学习-数据科学库 14 用户数据分析案例

数据准备

参考:https://github.com/CamDavidsonPilon/lifetimes/blob/master/lifetimes/datasets/CDNOW_master.txt

字段含义:

  • user_id :用户ID
  • order_dt : 购买日期
  • order_product : 购买数量
  • order_amount : 购买金额
# coding=utf8

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# CDNOW_master.txt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
df = pd.read_csv('./CDNOW_master.txt',
                 header=None,

                 # "\s+"则表示匹配任意多个上面的字符 *
                 sep="\s+",

                 # 使用指定索引
                 names=['user_id', 'order_dt', 'order_product', 'order_amount'])
print(df.head(5))
print(df.info())

# 将 order_dt 转换成时间序列
df['order_dt'] = pd.to_datetime(df['order_dt'], format='%Y%m%d')
print(df.info())
print(df.describe())

# 类型转换:在源数据中添加一列表示月份:astype(datetime64[‘M’])
# df["month"] = df["order_dt"].dt.to_period('M')
df["month"] = df["order_dt"].values.astype("datetime64[M]")
print(df.head())
print("*" * 100)

数据分析

按月对数据分析

# 按月对数据分析

# 用户每月花费的总金额
plt.figure(figsize=(8, 5))
plt.plot(df.groupby(by='month')['order_amount'].sum())
plt.xlabel('order_dt')
plt.ylabel('sum of amount')
plt.title('用户每月花费的总金额')
plt.legend()

# 所有用户每月的产品购买数量
plt.figure(figsize=(8, 5))
plt.plot(df.groupby(by='month')['order_product'].sum())
plt.xlabel('order_dt')
plt.ylabel('sum of amount')
plt.title('所有用户每月的产品购买数量')
plt.legend()

# 所有用户每月消费的总次数
plt.figure(figsize=(8, 5))
plt.plot(df.groupby(by='month')['user_id'].sum())
plt.xlabel('order_dt')
plt.ylabel('sum of amount')
plt.title('所有用户每月消费的总次数')
plt.legend()

# 每月的消费人数
plt.figure(figsize=(8, 5))
plt.plot(df.groupby(by='month')['user_id'].nunique())
plt.xlabel('order_dt')
plt.ylabel('sum of amount')
plt.title('每月的消费人数')
plt.legend()

在这里插入图片描述

用户个体消费数据分析

# 用户个体消费数据分析

# 所有用户消费总金额和消费总购买量的统计描述
print(df['order_product'].sum())
print(df['order_amount'].sum())
print("*" * 100)

# 用户维度消费金额和消费产品数量的散点图
user_amount = df.groupby(by='user_id')['order_amount'].sum()
user_product = df.groupby(by='user_id')['order_product'].sum()
plt.figure(figsize=(8, 8))
plt.scatter(user_product, user_amount)
plt.xlabel('product')
plt.ylabel('amount')
plt.title('用户维度消费金额和消费产品数量的散点图')

# 用户维度消费总金额的分布直方图(amount在1000之内)
order_amount_1000 = df.groupby(by='user_id').sum().query('order_amount <= 1000')['order_amount']
plt.figure(figsize=(8, 8))
plt.hist(order_amount_1000, bins=50)
plt.title('用户维度消费总金额的分布直方图(amount在1000之内)')

# 用户维度消费的总数量的分布直方图(消费商品的数量在100次之内的分布)
user_product_100 = df.groupby(by='user_id').sum().query('order_product <= 100')['order_product']
plt.figure(figsize=(8, 8))
plt.hist(user_product_100, bins=30)
plt.title('用户维度消费的总数量的分布直方图(消费商品的数量在100次之内的分布)')

在这里插入图片描述

用户消费行为分析

# 用户消费行为分析

# 用户第一次消费的月份分布,和人数统计
# 月份分布
plt.figure(figsize=(8, 8))

# 用户消费的最小值就是用户首次消费的月份
# value_counts() 用来统计 Series 中不同人数出现的次数
df.groupby(by='user_id')['month'].min().value_counts().plot()
df.groupby(by='user_id')['month'].max().value_counts().plot()
plt.title('用户第一次和最后一次消费的月份分布')

# 新老客户的占比
# agg 用于将分组后的结果进行多种不同形式的聚合操作:uid 分组后,用户维度购买时间的最大最小
first_last_order_dt = df.groupby(by='user_id')['order_dt'].agg(['min', 'max'])
print(first_last_order_dt.head(5))
print("*" * 100)

# True:只消费一次=新用户  False:消费多次=老用户
print((first_last_order_dt['min'] == first_last_order_dt['max']).value_counts())

# 求出每个用户的总购买量和总消费金额and最后一次消费的时间的表格rfm
# R 表示客户最近一次交易的时间间隔
# F 表示客户购买的商品数量 F 越大,表示客户交易越频繁,反之表示客户交易不够活跃
# M 表示客户交易的金额 M 越大,表示客户价值越高,反之价值越低
rfm = df.groupby(by='user_id').sum()
rfm['R'] = df.groupby(by='user_id')['order_dt'].max()

# 时间间隔 = 所有时间的最大值 - 客户最后一次交易的最大值
rfm['R'] = df['order_dt'].max() - rfm['R']

# np.timedelta64(1,'D'): 取出days
rfm['R'] = rfm['R'] / np.timedelta64(1, 'D')
rfm.columns = ['F', 'M', 'R']


# rfm分层算法
def rfm_func(x):
    # 存储的是三个字符串形式的0或者1
    # -6.122656	-94.310426	177.778362  ==》 '0'  '0'  '1'
    level = x.map(lambda x: '1' if x >= 0 else '0')
    label = level['R'] + level.F + level.M  # '100'
    d = {
        '111': '重要价值客户',
        '011': '重要保持客户',
        '101': '重要挽留客户',
        '001': '重要发展客户',
        '110': '一般价值客户',
        '010': '一般保持客户',
        '100': '一般挽留客户',
        '000': '一般发展客户',
    }
    result = d[label]  # d['100']
    # result ==》 '一般挽留客户'
    return result


# df.apply(func) :apply是DataFrame的运算工具  可以对df中的行或列进行某种func形式的运算
rfm['label'] = rfm.apply(lambda x: x - x.mean(), axis=0).apply(rfm_func, axis=1)
print(rfm.head(5))
print("*" * 100)

在这里插入图片描述

               min        max
user_id                      
1       1997-01-01 1997-01-01
2       1997-01-12 1997-01-12
3       1997-01-02 1998-05-28
4       1997-01-01 1997-12-12
5       1997-01-01 1998-01-03
****************************************************************************************************
True     12054
False    11516
dtype: int64
  rfm = df.groupby(by='user_id').sum()
          F       M      R   label
user_id                           
1         1   11.77  545.0  一般挽留客户
2         6   89.00  534.0  一般挽留客户
3        16  156.46   33.0  重要保持客户
4         7  100.50  200.0  一般发展客户
5        29  385.61  178.0  重要保持客户
****************************************************************************************************

用户的生命周期

# 用户的生命周期

# 统计每个用户每个月的消费次数
user_month_order_count = df.pivot_table(index='user_id', values='order_dt', aggfunc='count', columns='month',
                                        fill_value=0)
print(user_month_order_count.head(5))
print("*" * 100)

# 统计出每个用户每个月是否消费,消费记录为1 否则为0
df_purchase = user_month_order_count.applymap(lambda x: 1 if x >= 1 else 0)
print(df_purchase.head(5))
print("*" * 100)


# 对每月得用户活跃成分进行用户划分
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] == 'active':
                    status.append('return')
                elif status[i - 1] == 'unreg':
                    status.append('new')
                else:
                    status.append('active')
    return status


pivoted_status = df_purchase.apply(active_status, axis=1)
print(pivoted_status.head(5))
print("*" * 100)
df_purchase_new = pd.DataFrame(data=pivoted_status.values.tolist(),
                               index=df_purchase.index,
                               columns=df_purchase.columns)
print(df_purchase_new.head(5))
print("*" * 100)

# 每月【不同活跃】用户的计数
monthly_active = df_purchase_new.apply(lambda x:pd.value_counts(x)).fillna(0).T
print(monthly_active)
               min        max
user_id                      
1       1997-01-01 1997-01-01
2       1997-01-12 1997-01-12
3       1997-01-02 1998-05-28
4       1997-01-01 1997-12-12
5       1997-01-01 1998-01-03
****************************************************************************************************
True     12054
False    11516
dtype: int64
/Users/eddie/PycharmProjects/pythonProject/main.py:121: FutureWarning: The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
  rfm = df.groupby(by='user_id').sum()
          F       M      R   label
user_id                           
1         1   11.77  545.0  一般挽留客户
2         6   89.00  534.0  一般挽留客户
3        16  156.46   33.0  重要保持客户
4         7  100.50  200.0  一般发展客户
5        29  385.61  178.0  重要保持客户
****************************************************************************************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值