1 相关背景
数据来源:该数据集来自The UCI Machine Learning Repository
数据背景:该数据集是英国Argos 电商在2009-2011年内的全部在线销售数据,该电商主要销售独特的全时礼品,多数客户是批发零售商。该类产品的销售不需要太多的售前服务,消费也具有一定的频次。
分析目的:从海量购买数据中,挑选出优质客户,对客户进行细分并提出具有针对性的业务策略。
2 理解数据
1) 数据大小:1067371行数据,8个字段
2) 时间节点:2009年12月1日~2011年12月9日
3) 字段说明:
CustomerID:客户编号,每个客户分配唯一的5位整数
Quantity:每笔交易中每个产品(项目)的数量。
InvoiceDate:生成交易的日期和时间。
UnitPrice:单价,货币单位为英镑。
InvoiceNo:发票编号,每个交易分配唯一的6位整数。
StockCode:产品编号,每个不同产品分配唯一的5位整数。
Description:产品名称、描述。
Country:国家名称,客户居住国家或地区的名称。
3 数据处理
3.1导入数据
原数据集是以Excel表格的形式保存的,需要先另存为csv格式,再使用Navicat软件连接MySQL,将数据导入没有MySQL数据库中,并选筛选出进行用户价值分析所需字段:CustomerID、Quantity、InvoiceDate、UnitPrice。
##对应python代码
># 1. 创建一个数据库连接
conn=pymysql.connect(host='localhost',user='root',passwd='xxxx',db='school',port=3306,charset='utf8')
# 2. SQL语句
query1 = "(select CustomerID,Quantity,Price,InvoiceDate from year2010) union all (select CustomerID,Quantity,Price,InvoiceDate from year2011);"
# 3. 读
data = pd.read_sql_query(query1,conn)
3.2 数据清洗
3.2.1 查看数据质量
查看数据行列数、前五行数据、字段、数据类型、计算非空值个数及缺失率。
data.shape #查看数据行列数
data.head() #查看前五行数据
data.info() #查看字段、字段数据类型及数据个数
data.count() #计算非空值个数
data.apply(lambda x:sum(x.isnull())/len(x)) #计算缺失率
3.2.2 数据预处理
空值处理
四个字段对应的数据,只有CustomerID字段对应的数据存在22.7%的数据缺失,因为是做用户价值分析,分析CustomerID缺失的数据无意义,无法找到对应的客户,因此删除CustomerID为空值的数据。
datac = data.copy() #对原数据进行copy,防止破坏原数据
datac.dropna(axis=0,subset=['CustomerID'],how='any',inplace=True) #删除CustomerID为空值的数据。
datac.apply(lambda x:sum(x.isnull())/len(x)) #计算缺失率 ,检查数据是否还有空值
重复值处理
由于2009-2011年的数据是由2009-2010.csv和2010-2011.csv文件合并而成,因此存在大量的重复值,重复值对分析结果无益,而且会增大计算量,拖慢计算的速度,因此必须删除重复值。
any(datac.duplicated()) #检查数据中的重复值,结果返回True,存在重复值
datac.drop_duplicates(inplace=True) #存在重复值,删除重复值
any(datac.duplicated()) #检验是否还存在重复值,返回False,不存在重复值
异常值处理
异常值包括单价为小于等于零、产品数量小于等于零的数据,如果不删除这样的数据,直接进行运算,会造成计算结果出现错误,因此必须删除。
sum(datac['Price']<=0) #单价小于等于零的个数,返回结果为0,不存在单价小于等于零的数据
sum(datac['Quantity']<=0) #产品数量小于等于零的个数,返回结果16518,存在异常值
datac.drop(index=datac[datac['Quantity']<=0].index,inplace=True) #获取产品数量小于等于零的产品数量数据的index,并删除
datac[datac['Quantity']<=0] #再次检验是否产品数量小于等于零的数据,返回为null
3.2.3 数据转换
数据变换是在数据清洗完毕,为了分析方便,把数据进行计算,增加字段;转换数据的数据类型,方便计算
datac.info() #查看数据类型及数据个数
datac['Sales'] = datac['Quantity']*datac['Price'] #计算销售额
把CustomerID数据类型转成int类型
list1 = [] #创建空列表,存储数据
for i in datac['CustomerID'].values:
list1.append(int(i))
datac['CustomerID'] = list1
datac.info() #查看数据类型,看是否有新加字段及数据类型
到此数据清洗阶段完成,开始进行数据进一步打标签处理。因为数据是2009-2011,距现在比较远,所以设分析时间为2011-12-31 23:59:59 。
RFM模型
根据RFM模型,结合数据进行用户价值分析。R表示近度(Recency),也就是客户最近一次交易时间到现在的间隔,要注意,R是最近一次交易时间到现在的间隔,而不是最近一次的交易时间,R越大,表示客户未发生交易的时间越长;R越小,表示客户未发生交易时间越短。 F表示频度(Frequency),也就是客户在最近一段时间内的交易次数,F越大,表示客户交易越频繁,F越小,表示客户越不活跃。 M表示额度(Monetary),也就是客户在最近一段时间内的交易金额,M越大,表示客户价值越高;M越小,表示客户价值越低。R、F、M三个维度,根据分值分为高低两类。高,表示该指标高于平均值;低,表示该指标低于平均值。最终三个指标,每个指标分为高低两类,两两组合,就细分为八大客户群体。
R:用户最近一次购物,距2011-12-31 23:59:59的天数,R值越小越好
F:用户在2009-2011年的购物次数,F值越大越好
M:用户在2009-2011年的购物花费的总金额,M值越大越好
stat_time = pd.to_datetime('2011-12-31 23:59:59') #创建统计日期
result_data = pd.DataFrame() #创建一个新的数据框,存储计算数据
#计算R值
r_time = datac.groupby('CustomerID')['InvoiceDate'].max()
list2 = []
for i in stat_time - r_time:
list2.append(int(str(i).split(' ',1)[0]))
result_data['R'] = list2
#计算F值
list5 = []
for i in datac.groupby('CustomerID')['Sales'].count().tolist():
list5.append(i)
result_data['F'] = list5
#计算M值
list4 = []
for i in datac.groupby('CustomerID')['Sales'].sum().tolist():
list4.append(i)
result_data['M'] = list4
#添加CustomerID列
list6 = []
for i in datac.groupby('CustomerID')['CustomerID'].size().index:
list6.append(i)
result_data['CustomerID'] = list6
RFM计算值及对应CustomerID都添加到了新的数据框result_data中,一共5881行数据,下面对RFM值进行打分,首先查看数据的均值、最大小值、方差、25%、50%、75%分位数,确定打分区间,发现数据的极差大,方差也大,数据分散,难以等分成8份,结合分位数进行打分区间的确定。
result_data.describe() #查看数据均值、最大小值、方差、分位数
#设置R列评分区间,并评分
r_range = [0,100,200,300,400,500,600,700,800]
result_data['R_score'] = pd.cut(result_data['R'],bins=r_range,labels=[8,7,6,5,4,3,2,1])
result_data['R_score'] = result_data['R_score'].astype('int64')
#设置F列评分区间,并评分
f_range = [0,30,40,50,60,70,80,90,7000]
result_data['F_score'] = pd.cut(result_data['F'],bins=f_range,labels=[1,2,3,4,5,6,7,8])
result_data['F_score'] = result_data['F_score'].astype('int64')
#设置M列评分区间,并评分
m_range = [-1,20,50,100,500,1000,1500,2000,397200]
result_data['M_score'] = pd.cut(result_data['M'],bins=m_range,labels=[1,2,3,4,5,6,7,8])
result_data['M_score'] = result_data['M_score'].astype('int64')
计算评分的平均值,并与每个CustomerID对应RFM评分值与平均值比较,高于平均值的记为1,低于平均值的记为0。
result_data['R_score_label']=np.where(sum(result_data['R_score'])/len(result_data['R_score'])<result_data['R_score'],1,0)
result_data['F_score_label']=np.where(sum(result_data['F_score'])/len(result_data['F_score'])<result_data['F_score'],1,0)
result_data['M_score_label']=np.where(sum(result_data['M_score'])/len(result_data['M_score'])<result_data['M_score'],1,0)
将每个CustomerID对应RFM评分值打上1、0标签后,新建一个字典,将客户分为八组,打上标签。
d = { '011':'重要换回客户','111':'重要价值客户','001':'重要深耕客户','101':'重要挽留客户',
'010':'一般保持客户','110':'一般价值客户','100':'新客户','000':'流失客户' }
result_data['RFM_score_label']=result_data['R_score_label'].astype('str')+result_data['F_score_label'].astype('str')+result_data['M_score_label'].astype('str')
list3 = [] #建立新列表,存储每个CustomerID对应分组标签
for i in result_data['RFM_score_label'].tolist():
list3.append(d[i])
result_data['RFM_label'] = list3
至此数据处理部分完成,选出需要的字段每个CustomerID、R、F、M、RFM_label,并存成result_data.csv文件,方便下一步使用tableau进行数据分析。
datar = result_data[['CustomerID','R','F','M','RFM_label']]
datar.to_csv(r'C:\Users\Administrator\Desktop\result_data.csv')
4 数据分析
使用tableau读取使用python处理完毕的result_data数据源,进行分析
用户类型分布分析
从图上可看出,前三是流失客户、重要价值客户、新客户,其他类型客户占比小,需要进一步分析各分组客户销售额。
各分组客户分组人均消费分析
从图上可看出,前三是重要价值客户、重要挽留客户、重要唤回客户,其中重要价值客户人均消费远远高于其他分组客户。流失用户的人均消费为579.56K,排在第四,以促销折扣等方式回复客户兴趣,否则暂时放弃无价值的客户。
客户忠诚度分析
从图上可以看出,前三是重要价值客户、流失客户、一般价值客户,且重要价值客户忠诚度远远高于其他分组客户。
各类型客户交易额占比分析
从图上可以看出,前三是重要价值客户、重要挽留客户、重要唤回客户,且重要价值客户交易额远远高于其他分组客户。
RF—M流失分析
从图上可以看出,大部分客户的购物频次集中在0~1000,购物时间间隔在0~800分布较均匀,圆圈的大小和颜色表示客户购物花费的多少,颜色越红和圈越大,客户交易额越大。但是R值小、F值大的客户较少。
各类型客户消费汇总
从图上可以直观看出重要价值客户占比最大,且远远大于其他分组客户,点击每一个方块可以出现每个客户的编号、分组名、消费频次、交易额。
最后做一个可视化大屏,将上面的图表汇总。
5 结论与建议
本次分析涉及到5881位客户,他们的总交易金额12896888.42英镑。
高价值客户只占总人数的26.54%,却贡献了74.29%的交易额。虽然并不恰好是20%和80%,但情况基本符合帕累托法则。少数高价值客户支撑了大多数销售额,通过本次分析,就是要将这少数关键客户找出来,倾斜更多资源,VIP服务,个性化服务及附加销售等,对于公司的发展和业绩的增长起到帮助。
流失客户占总人数的32.65%,贡献了4.49%的交易额,但它的用户忠诚度排第二位,可以通过促销折扣等方式回复客户兴趣,否则暂时放弃无价值的客户。
新客户占总人数的22.12%,贡献了4.16%的交易额,用户忠诚度排第三位,可以通过促销折扣等方式回复客户兴趣,并进行用户留存运营,刺激客户消费,提高复购率。