【数据分析案例】用户消费行为
""" 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 版权协议,转载请附上原文出处链接和本声明。