【数据分析案例】用户消费行为

"""
user_ud 用户ID
order_dt: 购买日期
order_products: 购买产品数
order_amount: 购买金额
"""

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


pd.set_option(\'display.max_columns\', None)   #显示完整的列
pd.set_option(\'display.max_rows\', None)  #显示完整的行


plt.rcParams[\'font.sans-serif\']=[\'SimHei\'] #用来正常显示中文标签


columns = [\'用户ID\',\'购买日期\',\'购买产品数\',\'购买金额\']


data = pd.read_table(\'CDNOW_master.txt\',names=columns,sep=\'\s+\')  # names设置表头   \s+任意的空字符串




# 查看是否存在缺失值
# print(data.info())

# order_dt: 购买日期 转换成日期类型

# def time_style(x):
#    time = str(x)[0:4] + "-" +  str(x)[4:6]  + "-" + str(x)[6:8]
#    return time
# data[\'购买日期\'] = data[\'购买日期\'].apply(time_style)

data[\'购买日期\'] = pd.to_datetime(data[\'购买日期\'],format="%Y%m%d")
# print(data.head(3).dtypes)

# 计算每个用户购买商品的平均数量
# print(data.groupby(\'用户ID\')[\'购买产品数\'].mean())

# 计算所每个用户购买商品的平均花费
# print(data.groupby(\'用户ID\')[\'购买金额\'].mean())

# describe是描述统计 # 计算所有用户购买商品的平均数量
# print(data.describe())

#    M 对月进行统计
data[\'month\'] = data[\'购买日期\'].values.astype(\'datetime64[M]\')


print(data.head())





# 用户每月花费的总金额
use_months_by = data.groupby(\'month\')[\'购买金额\'].sum()
# print(use_months_by)
#
# plt.figure(figsize=(5,4))
# plt.plot(use_months_by.index,use_months_by.values,label="用户每月花费的总金额")
# plt.legend(loc=0)
# plt.savefig("用户每月花费的总金额.jpg")
# plt.show()


# 所有用户每月的产品购买量
# print(data.groupby(\'month\')[\'购买产品数\'].sum())


# 所有用户每月的消费总次数
# print(data.groupby(\'month\')[\'用户ID\'].count())

# 统计每月的消费人数    # 同一個人可能消費多次,所以 消费人数 只能是唯一的 .nunique() 去重后余下的
# print(data.groupby(\'month\')[\'用户ID\'].nunique())





# 各个用户消费总金额和消费总次数的统计描述
# print("各个用户消费总金额",data.groupby(\'用户ID\')[\'购买金额\'].sum())
# print("各个用户消费总次数",data.groupby(\'用户ID\')[\'购买产品数\'].nunique())



# print(data.groupby(\'用户ID\').sum().describe())

# 各个用户消费总金额和消费总次数的散点图
# plt.scatter(data.groupby(\'用户ID\').sum()[\'购买产品数\'],
#             data.groupby(\'用户ID\').sum()[\'购买金额\'])
# plt.xlabel("购买产品数")
# plt.ylabel("购买金额")
# plt.show()




# 各个用户消费总金额的直方分布图(消费金额在1000之内的分布)
# 總結:在groupby条件后直接限制条件, 限制条件后的结果取值 作图
# data_f = data.groupby(\'用户ID\').sum().query(" 购买金额 < 1000 " )[\'购买金额\']
# print(data_f)
# plt.hist(data_f,bins=10) # bins柱子的个数
# plt.show()



# 各个用户消费总次数的直方分布图(消费次数在于100内)
# by_number = data.groupby(\'用户ID\').sum().query(\'购买产品数 < 100\')[\'购买产品数\']
# print(by_number)
# plt.hist(by_number,bins=30)
# plt.show()


# 消费次数在100以内的  只有8个人消费次数超过100
# print((data[\'用户ID\'].value_counts() < 100).value_counts() )       # 每个data[\'用户ID\']出现的次数(出现次数 == 消费的次数)
# True     23562
# False        8


# 用户第一次消费的月的分布,和人数统计   month已经转成时间数据类型
# print(data.groupby(\'用户ID\')[\'month\'].min())  # 分组出用户ID,然后选出分组后每个用户ID最小的那个
# print(data.groupby(\'用户ID\')[\'month\'].min().value_counts()) # 每个月份的人数统计
# data.groupby(\'用户ID\')[\'month\'].min().value_counts().plot()  # 首购分布图
# plt.show()




# 用户最后一次消费的时间分布,人数统计
# print(data.groupby(\'用户ID\')[\'month\'].max())
# print(data.groupby(\'用户ID\')[\'month\'].max().value_counts())
# data.groupby(\'用户ID\')[\'month\'].max().value_counts().plot() # 最后一次购买的时间分布图
# plt.show()


# 新用户 (只购买一次)

# 获取每个用户的首购 跟尾够
# 第一种方式(结果是错误的)因为是一次消费的用户,所有只要挑出购买产品数为1的 )  学到的知识是 判断两数组对比方式
# data_left = data.groupby("用户ID")[\'month\'].agg([\'min\',\'max\']) # 得到min max日期
# print((data_left[\'min\'] == data_left[\'max\']).value_counts())

# print( (data.groupby("用户ID")[\'购买产品数\'].sum() == 1).value_counts().values) # 第二种方式[X,X1]




# 每个用户的总购买量 总消费金额  and 最近一次消费的表格rfm    (每个用户在最近的一次消费)
rfm = data.pivot_table(index=\'用户ID\',aggfunc={\'购买产品数\':\'sum\',\'购买金额\':\'sum\',\'购买日期\':\'max\',})

# 每个用户最近一次交易的时间间隔  (购买日期 - 购买日期的最大值) || 去掉days:  / np.timedelta64(1,\'D\')
rfm[\'R\'] = -(rfm[\'购买日期\'] - rfm[\'购买日期\'].max()) / np.timedelta64(1,\'D\')
# 修改名字
rfm.rename(columns={\'购买金额\':\'M\',"购买产品数":"F"},inplace=True)
# print(rfm.head())



# # 分层次
def rfm_func(x):
    level = x.map(lambda x:\'1\' if x >= 0 else \'0\') # 如果是负数的就是0,不是就是1
    laber = level.R + level.F + level.M  # 拼接成 d 对应的数值  进行区分客户等级
    d = {
        \'111\':\'重要价值客户\',
        \'011\':\'重要保持客户\',
        \'101\':\'重要挽留客户\',
        \'001\':\'重要发展客户\',
        \'110\':\'一般价值客户\',
        \'010\':\'一般保持客户\',
        \'100\':\'一般挽留客户\',
        \'000\':\'一般发展客户\',
    }
    result = d[laber]
    return result


rfm[\'laber\'] =rfm[[\'R\',\'F\',\'M\']].apply(lambda x: x - x.mean()).apply(rfm_func,axis=1)
# print(rfm)

# print(rfm.groupby(\'laber\').count())

#
# rfm.loc[rfm.laber == \'重要价值客户\',\'color\'] = \'g\'
# rfm.loc[~(rfm.laber == \'重要价值客户\'),\'color\'] = \'r\'
# rfm.plot.scatter("F",\'R\',c = rfm.color)
# plt.show()





# 统计每个用户每个月的消费次数
user_order_count_data = data.pivot_table(index=\'用户ID\',values=\'购买日期\',aggfunc=\'count\',columns=\'month\').fillna(0).head()
# 1               0           0           0           0           0           0
# 2               0           0           0           0           0           0



# 统计每个用户每个月是否消费 消费记录为1 否者记录消费为0
# apply 每一行的数据
# applymap() 每一个数据都执行一遍
data_purchase = user_order_count_data.applymap(lambda x:1 if x >= 1 else 0)
# print(data_purchase)




# 活跃用户判断

col = [\'1997-01-01\', \'1997-02-01\', \'1997-03-01\', \'1997-04-01\',
       \'1997-05-01\', \'1997-06-01\', \'1997-07-01\', \'1997-08-01\',
       \'1997-09-01\', \'1997-10-01\', \'1997-11-01\', \'1997-12-01\',
       \'1998-01-01\', \'1998-02-01\', \'1998-03-01\', \'1998-04-01\',
       \'1998-05-01\', \'1998-06-01\']


def active_status(data):
    status = []
    for i in range(18):

        # 若本月没有消费
        if data[i] == 0:
            if len(status) > 0:
                if status[i - 1] == \'unreg\':  # 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, index=col)

p_status = data_purchase.apply(active_status,axis=1)  # 将每一行数据执行函数一次
# print(p_status)


print(p_status.replace(\'unreg\',np.NAN).apply(lambda x:pd.value_counts(x)).T)

 

版权声明:本文为wanghong1994原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wanghong1994/articles/12950605.html