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

"""
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)