项目实战--用户消费数据分析
Posted 胜天半月子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了项目实战--用户消费数据分析相关的知识,希望对你有一定的参考价值。
引入包
本项目所用数据为【密码:pfj6】:CDNOW_master.txt
import numpy as np
import pandas as pd
from pandas import DataFrame,Series
import matplotlib.pyplot as plt
# CDNOW_master.txt
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
一、数据预处理
- 本阶段需求
- 读取数据集
df = pd.read_csv('./CDNOW_master.txt')
df.head()
消除列的索引,使用指定索引
# "\\s+"则表示匹配任意多个上面的字符 ⭐
df = pd.read_csv('./CDNOW_master.txt',header=None,sep='\\s+',names=['user_id','order_dt','order_product','order_amount'])
df.head()
- 查看数据类型
df.info()
- 将order_dt转换成时间序列
df['order_dt'] = pd.to_datetime(df['order_dt'],format='%Y%m%d')
df.info()
- 查看数据的统计描述
df.describe()
- 在源数据中添加一列表示月份:astype(datetime64[‘M’])
df['month'] = df['order_dt'].astype('datetime64[M]')
df.head()
astype的用法:np.astype()
Python中与数据类型相关函数及属性有如下三个:type/dtype/astype
- type() 返回参数的数据类型
- dtype 返回数组中元素的数据类型
- astype() 对数据类型进行转换
二、按月对数据分析
- 用户每月花费的总金额
df.groupby(by='month')['order_amount'].sum()
- 绘制曲线图
df.groupby(by='month')['order_amount'].sum().plot()
- 对上图进行细化
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()
- 所有用户每月的产品购买数量
df.groupby(by='month')['order_product'].sum()
df.groupby(by='month')['order_product'].sum().plot()
- 所有用户每月消费的总次数
df.groupby(by='month')['user_id'].count()
- 统计每月消费的人数 【有人会在同一天消费多次】
- unique():去重
- nunique():去重并统计个数
df.groupby(by='month')['user_id'].nunique()
三、用户个体消费数据分析
- 所有用户消费总金额和消费总购买量的统计描述
df['order_product'].sum()
167881
df['order_amount'].sum()
2500315.6300000004
- 各个用户消费金额和香消费产品数量的散点图
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')
- 各个用户消费总金额的分布直方图(amount在1000之内)
df.groupby(by='user_id').sum()
df.groupby(by='user_id').sum().query('order_amount <= 1000')
query的使用方法
order_amount_1000 = df.groupby(by='user_id').sum().query('order_amount <= 1000')['order_amount']
order_amount_1000
- 绘出直方图
plt.hist(order_amount_1000,bins=50)
上述结果大部分的消费在(0. , 19.9938)之间,有6.079e+03个人
- 各个用户消费的总数量的分布直方图(消费商品的数量在100次之内的分布)
user_product_100 = df.groupby(by='user_id').sum().query('order_product <= 100')['order_product']
plt.hist(user_product_100,bins=30)
四、用户消费行为分析
- 用户第一次消费的月份分布,和人数统计
如何判定用户第一次消费的月份?
- 用户消费的最小值就是用户首次消费的月份
# 月份分布
df.groupby(by='user_id')['month'].min()
人数统计
# value_counts() 用来统计Seris中不同人数出现的次数
df.groupby(by='user_id')['month'].min().value_counts()
df.groupby(by='user_id')['month'].min().value_counts().plot()
- 用户最后一次消费的时间分布和认数统计
df.groupby(by='user_id')['month'].max().value_counts()
df.groupby(by='user_id')['month'].max().value_counts().plot()
- 新老客户的占比
- 消费一次为新用户
- 消费多次为老用户
- 判定用户消费的次数(1次还是多次)
- 求出用户第一次和最后一次消费的时间,若时间相同,则表示用户只消费了一次,否则表示消费多次
# agg用于将分组后的结果进行多种不同形式的聚合操作
first_last_order_dt = df.groupby(by='user_id')['order_dt'].agg(['min','max'])
first_last_order_dt.head()
agg函数的使用:
(first_last_order_dt['min'] == first_last_order_dt['max']).value_counts()
# True:只消费一次--新用户 False:消费多次--老用户
True 12054
False 11516
dtype: int64
- 求出每个用户的总购买量和总消费金额and最后一次消费的时间的表格rfm
rfm = df.groupby(by='user_id').sum()
rfm.head()
# 最后消费一次的时间
user_recently_order_dt = df.groupby(by='user_id')['order_dt'].max()
rfm['R']=user_recently_order_dt
rfm.head()
- R表示客户最近一次交易的时间间隔
- /np.timedelta64(1,‘D’):去除days
- F表示客户购买的商品数量 F越大,表示客户交易越频繁,反之表示客户交易不够活跃
- M表示客户交易的金额 M越大,表示客户价值越高,反之价值越低
- 将R,F, M,作用到rfm中
rfm.columns = ['F','M','R']
rfm
# R : 表示客户最近一次交易的时间间隔
# 时间间隔 = 所有时间的最大值 - 客户最后一次交易的最大值
rfm['R'] = df['order_dt'].max() - rfm['R']
rfm
# / np.timedelta64(1,'D'):取出days
rfm['R'] = rfm['R'] / np.timedelta64(1,'D')
rfm.head()
- 划分客户类型⭐⭐
# 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)
rfm.head()
五、用户的生命周期
- 统计每个用户每个月的消费次数
# 每个用户消费在所有时间内的消费次数
df.pivot_table(index='user_id',values='order_dt',aggfunc='count').head()
df.pivot_table(index='user_id',values='order_dt',aggfunc='count',columns='month')
user_month_order_count = df.pivot_table(index='user_id',values='order_dt',aggfunc='count',columns='month',fill_value=0)
user_month_order_count.head()
- 统计出每个用户每个月是否消费,消费记录为1 否则为0
- applymap()函数用于对DataFrame中的每一个元素执行相同的函数操作
- apply()函数主要用于对DataFrame中的某一column或row中的元素执行相同的函数操作。
df_purchase = user_month_order_count.applymap(lambda x:1 if x>=1 else 0)
df_purchase.head()
- 对每月得用户活跃成分进行用户划分⭐⭐⭐
# 将df_purchase中的原始数据0和1修改为new,unactive ...,返回的df叫做df_purchase_new
# 固定算法
# data :每一行数据(某一个用户在不同月份的消费记录)
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
# 每一行作为参数传入active_status
pivoted_status = df_purchase.apply(active_status,axis=1)
pivoted_status.head()
- 需要将上述返回的Series封装到DataFrame中⭐⭐
pivoted_status.values
pivoted_status.values.tolist()
df_purchase_new = DataFrame(data=pivoted_status.values.tolist(),index=df_purchase.index,columns=df_purchase.columns)
df_purchase_new.head()
- 每月【不同活跃】用户的计数⭐
purchase_status_ct = df_purchase_new_apply(lambda:pd.value_counts(x)).fillna(0)
转置进行最终结果的查看
df_purchase_new.apply(lambda x:pd.value_counts(x))
- 将NaN用0填充
df_purchase_new.apply(lambda x:pd.value_counts(x)).fillna(0)
- 翻转
df_purchase_new.apply(lambda x:pd.value_counts(x)).fillna(0).T
以上是关于项目实战--用户消费数据分析的主要内容,如果未能解决你的问题,请参考以下文章
Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段
Flink实战系列Flink 1.14.0 消费 kafka 数据自定义反序列化器
概念+实战讲解!一文带你了解RFM模型kaggle项目实战分享数据分析