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