第一部分:数据类型的处理(预处理)
- 数据加载
- 字段定义:
- user_id:用户ID
- order_dt:购买日期
- order_product:购买产品的数量
- order_amount:购买金额
- 观察数据
- 查看数据的数据类型
- 数据中是否存在缺失值
- 将order_dt转换成时间类型
- 查看数据的统计描述
- 计算所有用户购买商品的平均数量
- 计算所有用户购买商品的平均花费
在源数据中添加一列表示月份:astype(‘datetime64[M]’)
import pandas as pd
import numpy as np
from pandas import DataFrame,Series
import matplotlib.pyplot as plt
df=pd.read_csv('./CDNOW_master.txt',header=None,sep='\s+',names=['user_id','order_dt','order_product','order_amount'])
#'sep=\s+'表示用N多个空格进行分割数据
#names属性填充列索引名称
df.info() #查看是否存在缺失数据
#将order_dt 转换成时间类型
df['order_dt']=pd.to_datetime(df['order_dt'],format='%Y%m%d')
df.info()
#查看数据的统计描述
df.describe() #转换成时间类型的数据不能参与到数值计算,所以只有显示剩余3列的结果
#基于order_dt取出其中的月份
df['order_dt'].astype('datetime64[M]')
#在源数据中添加一列表示月份:astype('datetime64[M]')
df['month']=df['order_dt'].astype('datetime64[M]') #将order_dt这列时间类型用astype('datetime64[M]')修改为月份
df.head()
第二部分:按月数据分析
#用户每月花费的总金额
every_month_amount=df.groupby(by='month')['order_amount'].sum()
every_month_amount.plot()
#所有用户每月的产品购买量
df.groupby(by='month')['order_product'].sum().plot()
#所有用户每月消费的总次数(原始数据中每一行都代表1次消费记录)
df.groupby(by='month')['user_id'].count() #count按月分组后计数消费记录的次数
#统计每月消费的人数(可能同1天1个用户会消费多次)
df.groupby(by='month')['user_id'].unique() #按月分组后unique()去除重复记录,消除1天1个用户多次消费的记录
df.groupby(by='month')['user_id'].nunique() # nunique 表示统计去重后的个数,是以数组形式(numpy.ndarray)返回列的所有唯一值
第三部分:用户个体消费数据分析
3.1 用户消费总金额和消费的总次数的统计描述
#每个用户消费总金额
df.groupby(by='user_id')['order_amount'].sum()
#每个用户消费的总次数
df.groupby(by='user_id')['order_dt'].count()
#用户消费金额和消费产品数量的散点图
user_amount_sum =df.groupby(by='user_id')['order_amount'].sum()
user_prount_sum = df.groupby(by='user_id')['order_product'].sum()
plt.scatter(user_amount_sum,user_prount_sum)
#各个用户消费的总金额的直方图(消费金额在1000以内的分布)
df.groupby(by='user_id').sum().query('order_amount <= 1000')['order_amount'] #query()过滤器 ,只能用于dataframe类型的数据 ###pandas的query()方法是基于dataframe列的计算代数式,对于按照某列的规则进行过滤的操作,可以使用query方法。< code></=>
df.groupby(by='user_id').sum().query('order_amount <= 1000')['order_amount'].hist()< code></=>
#各个用户消费的总数量的直方图分布情况(消费商品的数量在100次以内的分布)
df.groupby(by='user_id').sum().query('order_product <= 100')['order_product'].hist()< code></=>
第四部分:用户消费行为分析
#用户第一次消费的月份分布和人数统计
#第一次消费的月份:每一个用户消费月份的最小值就是该用户第一次消费的月份
df.groupby(by='user_id')['month'].min()
df.groupby(by='user_id')['month'].min().value_counts() #人数的统计
df.groupby(by='user_id')['month'].min().value_counts().plot()
#用户最后1次消费的时间分布和人数统计
#用户消费月份的最大值就是用户最后一次消费的月份
df.groupby(by='user_id')['month'].max()
df.groupby(by='user_id')['month'].max().value_counts()
df.groupby(by='user_id')['month'].max().value_counts().plot() #根据折线图可以观察用户在1-3月份流失率较高
新老用户的占比
- 消费1次为新用户,消费多次为老用户
如何获知用户是否为第一次消费?可以根据用户的消费时间进行判定,如果第一次消费和最后一次消费时间一样则为新用户,否则是老用户
- 方法一:用value_counts统计 对应关系:True–新用户 ,False–老用户
(df.groupby(by='user_id')['order_dt'].min()==df.groupby(by='user_id')['order_dt'].max()).value_counts()
2. 方法二:用agg函数,对分组后的结果进行多种指定形式的聚合
new_old_user_df=df.groupby(by='user_id')['order_dt'].agg(['min','max'])
new_old_user_df['min']==new_old_user_df['max'] #比较用户的第一次消费和最后1次消费的时间是否相等,True为新用户,Flase为老用户
(new_old_user_df['min']==new_old_user_df['max']).value_counts()
3. 方法三:用reset_index方法将新老用户的统计结果看成新的DataFrame,再分别统计两者的人数
f=df.groupby(by='user_id')['order_dt'].min()==df.groupby(by='user_id')['order_dt'].max() #判断哪些是新用户,新用户对应的值为True
df_user=f.reset_index() #将原有的索引user_id,作为新的一列并入DataFrame中
df_user['order_dt']==True
new_user=df_user.loc[df_user['order_dt']==True]['user_id'].count() #统计新用户的人数
old_user=df_user.loc[df_user['order_dt']==False]['user_id'].count() #统计老用户的人数
print('new_user:',new_user)
print('old_user:',old_user)
4. 根据价值分层,将用户分为:
- 重要价值客户
- 重要保持客户
- 重要挽留客户
- 重要发展客户
- 一般价值客户
- 一般保持客户
- 一般挽留客户
- 一般发展客户
RFM模型设计
通过三个指标来衡量该客户的价值状况
- R 最近一次消费的时间间隔 (Recency) 上一次消费离得越近,也就是R的值越小,用户价值越高。
- F 消费频率 (Frequency) 是指用户一段时间内消费了多少次 ,F值越大表示用户购买的越频繁,用户价值越高
- M 消费金额 (Monetary) 消费金额越高,M值越大,表示客户的价值越高
分析得出每个用户的总购买量和总消费金额and最近1次消费的时间的表格rfm
rfm = df.pivot_table(index='user_id',aggfunc={'order_product':'sum','order_amount':'sum','order_dt':'max'})
#R 表示用户最近1次消费的时间间隔
max_dt=df['order_dt'].max() #今天的日期
#每个用户最后一次交易的时间
user_last_dt=df.groupby(by='user_id')['order_dt'].max()
#时间间隔
(max_dt - user_last_dt)/np.timedelta64(1,'D') #np.timedelta64用于控制时间间隔
rfm['R'] = (max_dt - user_last_dt)/np.timedelta64(1,'D')
rfm.drop(labels='order_dt',axis=1,inplace=True) #删除'order_dt'这列
rfm.columns=['M','F','R']
rfm
'''rfm.apply(lambda x :x -x.mean()) #axis默认为0,表示案列计算
#apply函数用于DataFrame,对它的行或列进行操作
相当于Series类型里的map函数
'''
def rfm_func(x):
#存储的是三个字符串形式的0或1
level = x.map(lambda x :'1' if x >= 0 else '0')
label = level.R + level.F + level.M
d = {
'111':'重要价值客户',
'011':'重要保持客户',
'101':'重要挽留客户',
'001':'重要发展客户',
'110':'一般价值客户',
'010':'一般保持客户',
'100':'一般挽留客户',
'000':'一般发展客户'
}
result = d[label]
return result
#df.apply(func):可以对df中的行或列进行某种(func)形式的运算
rfm['label'] = rfm.apply(lambda x :x -x.mean()).apply(rfm_func,axis = 1)
rfm.head()
第五部分:用户的生命周期
#统计每个用户每个月的消费次数
user_month_count_df = df.pivot_table(index='user_id',values='order_dt',aggfunc='count',columns='month').fillna(0)
#统计每个用户每个月是否消费,消费记录为1否则记为0
df_purchase = user_month_count_df.applymap(lambda x:1 if x >= 1 else 0) #apply.map对DataFrame里的每一个元素进行操作
df_purchase
#将df_purchase中的原始数据0和1修改为new,unactive......,返回新的df叫做df_purchase_new
#固定算法
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 status
pivoted_status = df_purchase.apply(active_status,axis = 1)
pivoted_status.head()
pivoted_status.values.tolist()
df_purchase_new = DataFrame(data=pivoted_status.values.tolist(), index=df_purchase.index, columns=df_purchase.columns)
df_purchase_new
#每月【不同活跃】用户的计数
purchase_status_ct = df_purchase_new.apply(lambda x :pd.value_counts(x)).fillna(0) #按列把不同的值进行分组统计
purchase_status_ct.T #T转置
Original: https://blog.csdn.net/qq_42119837/article/details/123157998
Author: Lucky20171225
Title: 用户数据分析
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/739771/
转载文章受原作者版权保护。转载请注明原作者出处!