Python时空大数据数据分析呆鸟的Python数据分析

案例分析三——UK Retailer 购物行为分析(RFM模型)

2020-06-14  本文已影响0人  粉红狐狸_dhf

1 项目背景

(1)数据

Kaggle数据源。英国零售商的实际交易数据,包含了2010年12月1日至2011年12月9日在英国注册的非实体网上零售发生的所有交易。公司主要销售独特的全天候礼品。该公司的许多客户都是批发商。本篇基于Python进行分析,还有一篇是基于SQL语言进行的分析

(2)分析目的

采用RFM模型,从用户、地区和时间等维度分析用户行为并提出优化建议。

2 理解数据

InvoiceNo --> 订单号码: 6位字符串
StockCode --> 产品代码: 6位字符串
Description --> 产品描述
Quantity --> 产品数量:交易产品数量
InvoiceDate --> 订单日期:订单发生的日期和时间
UnitPrice --> 单价:浮点数值
CustomerID --> 顾客ID:5位字符串
Country --> 国家:客户所在地

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')

import plotly as py
import plotly.graph_objs as go
pyplot = py.offline.iplot
py.offline.init_notebook_mode()

df = pd.read_csv(r'E:\jupyter_lab\leetcode\data\UK retailer-kaggle\data.csv',encoding='ISO-8859-1',dtype={'CustomerID':str}) 
df.head()
360截图176106119511198.png
df.info()
360截图1872011583114132.png

3 数据清洗

(1) 空值 :空值是什么?没有影响的删掉,有影响的填充。
(2) 去重操作(看情况分析)。
(3) 数据格式:时间格式(日期表示)、字符格式、类别格式(编码问题)。
(4) 异常值分析(describe:负数,极值等)。此处,负数代表退货。
(5) 计算一些分析用到的统计变量。

(1)空值
df.apply(lambda x : sum(x.isnull())/len(x)) #缺失率
df.isnull().sum() #缺失值个数
(2)重复值、无用字段 和 空值填充
df=df.drop_duplicates()
df.drop(['Description'],axis=1,inplace=True) #按列操作,默认是删除行的
df.CustomerID = df.CustomerID .fillna('U') #U表示customer_id缺失
(3)数据格式转化
df['date'] = [x.split(' ')[0] for x in df.InvoiceDate ] #月-日-年
df['time'] = [x.split(' ')[1] for x in df.InvoiceDate ]
df.drop(['InvoiceDate'],axis=1,inplace=True)

df['year'] = [x.split('/')[2] for x in df.date]
df['month'] = [x.split('/')[0] for x in df.date]
df['day'] = [x.split('/')[1] for x in df.date]

df['date'] = pd.to_datetime(df.date)

df['year']=pd.to_numeric(df['year'])
df['month']=pd.to_numeric(df['month'])
df['day']=pd.to_numeric(df['day'])
#是数字的一定变成数字,不然排序的时候不灵光
(4)异常值分析
df.describe() #数据探索,异常值分析
360截图16720402111152114.png
#禁用科学计数法
pd.set_option('display.float_format',lambda x : '%.2f' % x)
pd.options.display.float_format = '{:,.2f}'.format

df2 = df[df['UnitPrice']<=0]
df2.shape[0]/df.shape[0] #单价为负值的比例

0.00468

#分类统计方法一
df2.UnitPrice.groupby(df2.UnitPrice).count()
#分类统计方法二
from collections import Counter
Counter(df.UnitPrice)
360截图1672033173103102.png
(5)统计一些分析用到的变量
df['amount'] = df.Quantity * df.UnitPrice #消费总金额

4 数据分析

该是数值的地方一定在数据处理的时候改成数值类型,不然在排序的时候打死你也不知道为什么不能排序

(1)退货率=退货金额/销售金额

df1 = df[df.Quantity<=0]

sales_return = pd.pivot_table(df1,index=['year'],columns=['month'],values=['amount'],aggfunc=np.sum,fill_value=0)

df2 = df[(df.Quantity>0) & (df.UnitPrice>0)]
sales = pd.pivot_table(df2,index=['year'],columns=['month'],values=['amount'],aggfunc=np.sum,fill_value=0.001)

return_goods_ratio=np.abs(sales_return/sales)

return_goods_ratio.sort_index(level=1,axis=1,inplace=True) 
360截图18290329726667.png

这涉及多重索引,下面是数据提取的一些方法。

return_goods_ratio.iloc[0,:].index.levels[1]

return_goods_ratio.iloc[1,:]
按照month 排序,然后把amount绘制出来
data_2011 = pd.DataFrame({'return_ratio':return_goods_ratio.iloc[1,:]})
data_2011 = data_2011.iloc[:,-1].reset_index().iloc[:,1:]

%matplotlib inline
plt.plot(data_2011.month,data_2011.return_ratio)
360截图18720122103705.png
return_goods_ratio.iloc[1,:].mean()
#2011年退货的平均数 0.092

(2)RFM模型

R_value = df2.groupby('CustomerID').date.max()

R_value = (df2.date.max()-R_value).dt.days
#每位客户最近一次购买时间到参考日期的时间间隔(此值越小越好)

F_value = df2.groupby('CustomerID').InvoiceNo.nunique() #唯一值的个数
#每位客户的购买频率(此值越大越好

M_value = df2.groupby('CustomerID').amount.sum() 
#每位用户的消费总金额(此值越大越好)
(2.1)探索RFM数据
R_value.describe()
360截图187201248212296.png

可视化一:

sns.distplot(R_value,bins=30)
360截图17650105739789.png

可视化二:

plt.hist(R_value,bins=30)
plt.show()
360截图168004118911176.png

同理于消费频次与购买金额的分析。在此略过。

(2.2) RFM分级

指定分割段

R_bins = [0,30,90,180,360,720]

通过分位数指定分割段

F_value.quantile([0.1,0.2,0.3,0.4,0.5,0.9,1])
F_bins = [0,2,10,100,1000,2000]

M_value.quantile([0.1,0.2,0.3,0.4,0.5,0.9,1])
M_bins = [100,200,500,5000,100000,2000000]

依据分割段分割

R = pd.cut(R_value,R_bins,labels=[5,4,3,2,1],right=False)
#不包含上线  越小越好
F = pd.cut(F_value,F_bins,labels=[1,2,3,4,5],right=False)
#不包含上线
M = pd.cut(M_value,M_bins,labels=[1,2,3,4,5],right=False)
#不包含上线

rfm = pd.concat([R,F,M],axis=1)
#按列操作,扩展
rfm.rename(columns={'date':'R_score','InvoiceNo':'F_score','amount':'M_score'},inplace=True)
rfm.head()
360截图17411027432772.png

看一下rfm的数据类型

rfm.info()
360截图16720401180641.png
(2.3) 数据类型的转化,便于计算
for i in rfm.columns:
    rfm[i] = rfm[i].astype(float)

依据平均值划分客户类型

rfm['R'] = np.where(rfm['R_score']>rfm['R_score'].mean(),'高','低')
rfm['F'] = np.where(rfm['F_score']>rfm['F_score'].mean(),'高','低')
rfm['M'] = np.where(rfm['M_score']>rfm['M_score'].mean(),'高','低')

rfm['values'] = rfm.R.str[:]+rfm.F.str[:]+rfm.M.str[:]
rfm['values']=rfm['values'].str.strip()

定义客户类型的函数

def class_func(x):
    if x == '高高高':
        return '重要价值客户'
    elif x == '高低高':
        return '重要发展客户'
    elif x == '低高高':
        return '重要保持客户'
    elif x == '低低高':
        return '重要挽留客户'
    
    elif x == '高高低':
        return '一般价值客户'
    elif x == '高低低':
        return '一般发展客户'
    elif x == '低高低':
        return '一般保持客户'
    else:
        return '一般挽留客户'

将客户类型映射到函数上,得到客户等级

rfm['用户等级'] = rfm['values'].apply(class_func)
rfm.head()
360截图16780702407079.png

存一下数据

rfm.to_csv(r'E:\jupyter_lab\leetcode\data\UK retailer-kaggle\rfm.csv')
(2.4) RFM可视化

条形图

trace_base = [go.Bar(x=rfm['用户等级'].value_counts().index,
                    y=rfm['用户等级'].value_counts().values
                   , marker=dict(color='orange'),opacity=0.5
                    )]
layout = go.Layout(title='用户等级分布',xaxis=dict(title='用户等级'))

figure_base = go.Figure(data=trace_base,layout=layout)

pyplot(figure_base, auto_open=True)
newplot.png

饼图

trace_pie = [go.Pie(labels=rfm['用户等级'].value_counts().index,
                    values=rfm['用户等级'].value_counts().values
                   , textfont=dict(color='orange',size=12))]
layout = go.Layout(title='用户等级比例',xaxis=dict(title='用户等级'))

figure_base = go.Figure(data=trace_pie,layout=layout)

pyplot(figure_base, auto_open=True)
pie.png

5 结论与对策

(1)1月与12月的退货率比较高,我们要对比往年同时间段的退货率,如果与往年不同,此时我们要继续分析退货率增加的原因。
(2)由RFM模型可知,客户类型中占比最多的是“重要价值客户”(最近购买了,购买频率还挺高,购买金额也挺大)此时,应向该部分人群继续推送公司主营业务,通过宣传推广等手段,让产品信息送达客户手中。其次,占比较多的是“一般挽留客户”(很长时间没买了,购买的频率比较低,购买的金额也比较少),公司应该面向该部分人群推出促销活动,拉动消费的积极性。

上一篇下一篇

猜你喜欢

热点阅读