其实这是一个做了好久的外包
给大家来分享一下其中的思路
有什么python相关报错解答自己不会的、或者源码资料/模块安装/
女装大佬精通技巧都可以来这里:(https://jq.qq.com/?_wv=1027&k=2Q3YTfym)
通过"扫描"零售商店电子销售点个别产品的条形码而获得的消费品销售的详细数据。这些数据提供了有关所售商品的数量、特征和价值以及价格的详细信息。
<链接>
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import 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()
第一列为数据编号,已有索引故删除
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
df[['Quantity','Sales_Amount']].describe()
购买数量存在小于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()
由上图可知:每月购买人数可分简单为三个阶段,1-5月呈持续上升趋势,6—8呈持续下降趋势,9-12月呈波动上升趋势
(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()
由上图可知:每月新用户占比整体呈下降趋势,结合每月消费人数趋势可知,第四季度消费人数有上升趋势,故期间复购人数有所提升
(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()
由上图可知:
(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)
由上图可知:
(2)用户生命周期价值分布
clv['Sales_Amount'].plot.hist(bins = 50)
由上图可知:
(3)用户生命周期及其价值相关关系
plt.scatter(x='lifetime', y='Sales_Amount', data=clv)
由上图可知:
(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()
由上图可知:90天内回购率,即90天内重复购买率在10%以下,说明目前商店处于用户获取模式,然而由前面分析可知,新用户获取呈下降趋势,目前商店并不健康,当前阶段应当将重心放在新用户获取上,
(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.02
min_confidence_value = 0.3
result = list(apriori(transactions=category_list, min_support=min_support_value, min_confidence=min_confidence_value, min_left=0))
result
由上结果可得: