前言嗨喽!大家好呀,这里是魔王~ 一、项目背景通过"扫描"零售商店电子销售点个别产品的条形码而获得的消费品销售的详细数据。这些数据提供了有关所售商品的数量、特征和价值以及价格的详细信息。 二、数据来源<链接> 三、提出问题消费情况分析及用户购买模式分析 RFM和CLV分析 不同类别商品关联规则挖掘
四、理解数据Date:购买日期 Customer_ID:用户ID Transaction_ID:交易ID SKU_Category:商品分类SKU编码 SKU:商品唯一SKU编码 Quantity:购买数量 Sales_Amount:购买金额
五、数据清洗1.导入数据import numpy as npimport pandas as pd from matplotlib import pyplot as pltimport seaborn as sns %matplotlib inline # 更改设计风格 plt.style.use('ggplot') plt.rcParams['font.sans-serif'] = ['SimHei']
np.__version__
pd.__version__
df = pd.read_csv('scanner_data.csv') df.head()
df.info()
2.选择子集第一列为数据编号,已有索引故删除
df.drop(columns='Unnamed: 0', inplace=True) df.info()
### 3.删除重复值```go df.duplicated().sum()
数据无重复值 ### 4.缺失值处理
df.isnull().sum()
数据无缺失值 ### 5.标准化处理
df.dtypes
Date为对象类型,需要标准化为日期类型格式
df.Date = pd.to_datetime(df.Date, format='%d/%m/%Y') df.dtypes
6.异常值处理df[['Quantity','Sales_Amount']].describe()
购买数量存在小于1是由于称重单位不足1所致,非异常值 六、分析内容1.消费情况按月分析(1)每月消费总金额趋势分析 df['Month'] = df.Date.astype('datetime64[M]') df.head()
grouped_month = df.groupby('Month')
grouped_month.Sales_Amount.sum()2018年1月数据可能统计不全,不纳入趋势分析
grouped_month.Sales_Amount.sum().head(12).plot()
(2)每月交易次数趋势分析 grouped_month.Transaction_ID.nunique().head(12).plot()
(3)每月商品购买数量趋势分析 grouped_month.Quantity.sum().head(12).plot()
(4)每月消费人数趋势分析 grouped_month.Customer_ID.nunique().head(12).plot()
2.用户分布分析(1)新用户分布 grouped_customer = df.groupby('Customer_ID') grouped_customer.Date.min().value_counts().plot()
grouped_customer.Month.min().value_counts().plot()
(2)一次消费及多次消费用户占比分析 #仅消费一次用户占比
(grouped_customer.Transaction_ID.nunique() == 1).sum()/df.Customer_ID.nunique()
grouped_month_customer = df.groupby(['Month', 'Customer_ID'])
#每个用户每月的第一次购买时间 data_month_min_date = grouped_month_customer.Date.min().reset_index() #每个用户的第一次购买时间 data_min_date = grouped_customer.Date.min().reset_index()
#通过Customer_ID联立两表 merged_date = pd.merge(data_month_min_date, data_min_date, on='Customer_ID') merged_date.head()
#Date_x等于Date_y则为每月新用户 ((merged_date.query('Date_x == Date_y')).groupby('Month').Customer_ID.count() / merged_date.groupby('Month').Customer_ID.count()).plot()
3.用户分层分析(1)RFM分层分析 pivot_rfm = df.pivot_table(index='Customer_ID', values=['Date', 'Transaction_ID', 'Sales_Amount'], aggfunc={'Date':'max', 'Transaction_ID':'nunique', 'Sales_Amount':'sum'})
pivot_rfm['R'] = (pivot_rfm.Date.max() - pivot_rfm.Date)/np.timedelta64(1, 'D') pivot_rfm.rename(columns={'Transaction_ID':'F', 'Sales_Amount':'M'}, inplace=True)
def label_func(data): label = data.apply(lambda x:'1' if x > 0 else '0') label = label.R + label.F + label.M labels = { '111':'重要价值客户', '011':'重要保持客户', '101':'重要发展客户', '001':'重要挽留客户', '110':'一般价值客户', '010':'一般保持客户', '100':'一般发展客户', '000':'一般挽留客户' } return labels[label] pivot_rfm['label'] = pivot_rfm[['R','F','M']].apply(lambda x:x-x.mean()).apply(label_func, axis=1)
pivot_rfm.label.value_counts().plot.barh()
pivot_rfm.groupby('label').M.sum().plot.pie(figsize=(6,6), autopct='%3.2f%%')
pivot_rfm.groupby('label').agg(['sum', 'count'])
由上表及图可知: 销售额主要来源重要保持客户,人数占比最高的为一般发展客户 重要保持客户:销售额的主要来源,近期有消费,且消费高,消费频率不足,可以适当举行营销活动,提升此层客户的购买频率 重要价值客户:销售额的第二来源,近期有消费,消费高,频率高,尽可能使该层客户保持现状 重要发展客户:消费以及消费频次高,近期没有消费,可以使用适当策略召回用户,参与消费 重要挽留客户:消费高,但频次低且近期未消费,处在流失的边缘,可以通过适当活动,使其参与到消费中来,防止流失 一般价值客户:消费低,消费频率高且近期有消费,可以使用优惠券等形式活动刺激该层客户的消费,提升其消费额 一般发展客户:人数占比最高,近期有消费,但消费额以及消费频次不高,考虑到人数占比高,可以适当举办活动提升消费频次和消费额 一般保持客户:在成本与资源控制下,酌情考虑 一般挽留客户:在成本与资源控制下,酌情考虑
(2)用户状态分层分析 pivoted_status = df.pivot_table(index='Customer_ID', columns='Month', values='Date', aggfunc='count').fillna(0)
def active_status(data): status = [] for i in range(len(data)): #若本月没有消费 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: if status[i-1] == 'unreg': status.append('new') elif status[i-1] == 'unactive': status.append('return') else: status.append('active') else: status.append('new') status = pd.Series(status, index = data.index) return status
active_status = pivoted_status.apply(active_status, axis=1)
active_status.replace('unreg', np.nan).apply(lambda x:x.value_counts()).fillna(0).T.apply(lambda x: x/x.sum(),axis=1).plot.area()
由上图可知: 新用户:新用户占比呈明显下降趋势,说明拉新运营不足 活跃用户:在二月占比达到最高,后续呈缓慢下降趋势,说明消费运营正在下滑 不活跃用户:不活跃用户呈明显上升趋势,客户流失较为明显 回流客户:有缓慢上升趋势,说明召回运营不错
4.用户生命周期分析(1)用户生命周期分布 #构成用户生命周期研究的数据样本需要消费次数>=2次的用户 clv = (grouped_customer[['Sales_Amount']].sum())[grouped_customer.Transaction_ID.nunique() > 1]
clv['lifetime'] = (grouped_customer.Date.max() - grouped_customer.Date.min())/np.timedelta64(1,'D')
clv.describe()
- 由上表可知:消费一次以上的用户平均生命周期为116天,用户生命周期内平均消费金额为121.47元
clv['lifetime'].plot.hist(bins = 50)
由上图可知: 生命周期在0-90天内的用户较多,说明生命周期短的客户占比较高,90天内流失率较高,此部分用户可以作为运营重点,延长这些用户的生命周期; 生命周期在90-250之间的分布较为均匀,这也是大多数用户的生命周期,可以刺激这些用户的消费,使其在生命周期内提升消费金额; 生命周期大于250天的人数极少,说明生命周期较长的忠诚客户占比不高。
(2)用户生命周期价值分布 clv['Sales_Amount'].plot.hist(bins = 50)
由上图可知: (3)用户生命周期及其价值相关关系 plt.scatter(x='lifetime', y='Sales_Amount', data=clv)
由上图可知: 5.回购率与复购率分析(1)复购率分析 grouped_month_customer
customer_month_again = grouped_month_customer.nunique() customer_month_again
#每月消费次数大于1的用户数 customer_month_again = grouped_month_customer.nunique().query('Transaction_ID > 1').reset_index().groupby('Month').count().Customer_ID # customer_month_again #每月消费用户数 customer_month = grouped_month.Customer_ID.nunique() # #每月复购率 (customer_month_again/customer_month).plot() customer_month (customer_month_again/customer_month)
(2)回购率分析 # 1表示前90天消费且本月回购 0表示前90天消费本月未回购 nan表示前90天未消费 def buy_back(data): status = [np.nan,np.nan,np.nan] for i in range(3,len(data)): #本月购买 if data[i] == 1: #前90天购买 if (data[i-1] == 1 or data[i-2] ==1 or data[i-3] == 1): status.append(1) #前90天未购买 else: status.append(np.nan) #本月未购买 else: #前90天购买 if (data[i-1] == 1 or data[i-2] ==1 or data[i-3] == 1): status.append(0) #前90天未购买 else: status.append(np.nan) status = pd.Series(status, index = data.index) return status
back_status = pivoted_status.apply(buy_back, axis=1) back_status.head()
(back_status.sum()/back_status.count()).plot()
6.商品关联规则挖掘(1)分析热销商品 #取出销量排名前10的商品类型 hot_category = df.groupby('SKU_Category').count().Sales_Amount.sort_values(ascending=False)[:10].reset_index() plt.barh(hot_category.SKU_Category, hot_category.Sales_Amount)
#热销商品占比 hot_category['percent'] = hot_category.Sales_Amount.apply(lambda x:x/hot_category.Sales_Amount.sum()) plt.figure(figsize=(6,6)) plt.pie(hot_category.percent,labels=hot_category.SKU_Category,autopct='%1.2f%%') plt.show()
category_list = df.groupby('Transaction_ID').SKU_Category.apply(list).values.tolist()
from apyori import apriori
min_support_value = 0.02min_confidence_value = 0.3result = list(apriori(transactions=category_list, min_support=min_support_value, min_confidence=min_confidence_value, min_left=0))
result
由上结果可得: 'FU5’-->'LPF’:支持度为约2.1%,置信度约为49.5%。说明同时购买这两类商品发生的可能性为约2.1%,先购买FU5类型产品后,同时购买LPF类型产品的概率为49.5% 'IEV’-->'LPF’:支持度约为3.1%,置信度约为48.9%。说明同时购买这两类商品发生的可能性约为3.1%,先购买IEV类型产品后,同时购买LPF类型产品的概率约为48.9% 'LPF’-->'IEV’:支持度约为3.1%,置信度约为43.3%。说明同时购买这两类商品发生的可能性约为3.1%,先购买LPF类型产品后,同时购买IEV类型产品的概率约为43.3% 'OXH’-->'LPF’:支持度约为2.0%,置信度约为48.1%。说明同时购买这两类商品发生的可能性约为2.0%,先购买IEV类型产品后,同时购买LPF类型产品的概率约为48.1%
尾语好了,我的这篇文章写到这里就结束啦! 有更多建议或问题可以评论区或私信我哦!一起加油努力叭(ง ·_·)ง 喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!
|