Apriori算法是一种挖掘关联规则的频繁项集算法,其核心思想是通过候选集生成和情节的向下封闭检测两个阶段来挖掘频繁项集,而且算法已经被广泛的应用到商业,网络安全等各个领域。
购物篮分析是通过发视频顾客再一次购物行为中放入购物篮中不同商品之间的关联,研究客户的购买行为,从而辅助零售企业制定营销策略的一种数据分析方法。
使用Apriori关联规则算法实现购物篮分析,发现超市不同商品之间的关联关系,并根据商品之间的关联规则制定营销策略。
繁杂的选购过程选购过程往往会给顾客疲惫的购物体验。对于某些商品顾客会选择同时购买,如可乐和汉堡,蛋糕和酸奶,当可乐和汉堡或者蛋糕和酸奶分布在商场的两侧,且距离十分遥远时,顾客购买的欲望会减少,在时间紧迫的情况下顾客甚至会放弃购买某些计划购买的商品。相反,如果放在相邻的位置,即给顾客提供便利,提升购物体验,又提高顾客购买的频率,达到了促销的目的。很多商场往往会以打折方式作为主要促销手段,以更少的利润为代价获得更高的销售。但好多商店不知道,打折的吸引力远远不足。而正确的商品摆放却能提醒顾客购买某些必需品,甚至吸引他们购买兴趣的商品。
为了销售最大的利润,货摆放的位置很重要,所以应该了解客户的购买习惯和偏好。通过对商场销售数据分析,可以获得顾客的购买行为特征,这样可以发现的规律而采取有效的行动。制定商品摆放,商品定价,新商品采购计划,对商场增加销售至关重要。
挖掘目标还应该考虑的是:1.从什么样的途径获取客户信息;2.有那些可用的资源;3目标客户挖掘的正确办法等。
根据提供的数据可以实现以下几个目标:1,构建零售商品的Apriori关联规则模型,分析商品之间的关联性;2,根据模型结果给出有效的销售策略,提升销售量。
本次数据挖掘建模的总体流程如图所示:
业务系统 | 数据抽取 | 数据搜索与预处理 | 分析与建模 | 结果反馈 |
源数 据 |
某商品零售企业购物篮数据 | 查看数据特征 |
Apriori关联规则分析 | 模型优化 |
热销商品分析 | ||||
商品结构分析 | 模型应用 | |||
数据转换 |
购物篮关联规则挖掘主要步骤如下:1.对原始数据进行数据探索性分析,分析商品的热销情况与商品结构;2,对原始数据进行数据预处理,转换数据形式,使之符合Apriori关联规则算法要求;3,在步骤2得到的建模数据基础上,采用Apriori关联规则算法,调整模型输入参数,完成商品关联性分析;4.结合实际业务,对模型结果进行分析,根据分析结果给出销售建议,最后输出关联规则结果。
本案列的探索性分析是查看数据特征,以及对商品热销情况和商品结构分析。
探索数据特征是了解数据的第一步。分析商品热销情况和商品结构,是为了更好地实现企业的经营目标。商品管理应坚持商品齐全和商品优选的原则,产品销售基本满足“二八定律”即80%的销售额是由20%的商品创造的,这些商品是企业主要盈利商品,要作为商品管理的重中之重。商品热销情况分析和商品结构分析也是商品管理不可或缺的一部分,其中商品结构分析能够帮助保证商品的齐全性,热销情况分析可以助力于商品优选。某商品零售企业共收集了9835个购物篮的数据,购物篮数据主要包括3个属性:id,Goods和Types。属性具体说明如表:
表格 | 属性名称 | 属性说明 |
GoodsOrder | id | 商品所属类别的编号 |
Goods | 具体的商品名称 | |
GoodsTypes | Goods | 具体的商品名称 |
Types | 商品类别 |
探索数据的特征,查看每列属性,最大值,最小值,是了解数据的第一步,查看数据特征,如代码清单所示:
import numoy as np
import pandas as pd
inputfile ='../data/GoodsOrder.csv' #输入的数据文件
data =pd.read_csv(inputfile,encoding='gbk') #读取数据
data.info() #查看数据属性
data=data['id']
description=[data.count(),data.min(),data.max()] #依次计算总数,最小值,最大值
description=pd.
DataFrame(description,index=['Count','Min','Max']).T #将结果存入数据框
print('描述性统计结果:/n',np.round(description)) #输出结果
清单可得,每列属性共有共有43367个观测值,并不存在缺失值。查看“id"属性的大值和最小值,可知某商品零售企业共收集了9835个购物篮的数据,其中包含169个不同的商品类别,售出商品总数为43367件。
计算销售量排行前10商品的销量及占比,并绘制条形图显示销量前10商品的销量情况,如代码清单所示:ge
#销量排行前10商品的销量及其占比
import pandas as pd
inputfile='../data/GoodsOrder.csv' #输入的数据文件
data=pd.read_csv(inputfile,encoding='gbk') #读取数据
group =data.groupby(['Goods']).count().reset_index() #对商品进行分类汇总
sorted=group.sort_values('id',ascending=False)
print('销量排行前10商品的销量:/n'.sorted[:10]) #排序并查看前10位热销商品
#画条形图展示出销量排行前10商品的销量
import matplotlib.pyplot as plt
x=sorted[:10]['Goods']
y=sorted[:10]['id']
plt.figure(figsize=(8,4)) #设置画布大小
plt.barh(x,y)
plt.xlabel('销量’) #设置x轴标题
plt.ylabel('商品类别') #设置y轴标题
plt.ylabel('商品的销量TOP') #设置标题
plt.savefig('../tmp/top10.png') #把图片以.png格式保存
plt.show() #展示图片
#销量排行前10商品的销量占比
data_nums=data.shape[0]
for idnex, row in sorted[:10].iterrows():
print(row['Goods'],row['id'],row['id']/data_nums)
根据代码清单可得到销量排行前10商品的销量及其占比情况,如表图所示:
商品名称 | 销量 | 销量占比 |
全脂牛奶 | 2513 | 5.795% |
其他蔬菜 | 1903 | 4.388% |
面包卷 | 1809 | 4.171% |
苏打 | 1715 | 3.955% |
酸奶 | 1372 | 3.164% |
瓶装水 | 1087 | 2.507% |
根茎类蔬菜 | 1072 | 2.472% |
热带水果 | 1032 | 2.380% |
购物袋 | 969 | 2.234% |
香肠 | 924 | 2.131% |
通过分析热销量商品的结果可知,全脂牛奶销量最高,销量为2513件,占比5.795%;其次是其他蔬菜,面包卷和苏打,占比分别为4.388%,4.171%,3.955%。
我们应该多分析商品热销程度的进行情况,这样有利于商家在制定商品在货架的摆放策略和位置。若销售量比较高,咱们就放在中心位置,方便给顾客购买。或者放在深处位置,是顾客在购买热销商品前经过非热销商品,增加在非热销商品处的停留时间,促进非热销产品的销量。
原始数据中的商品本身已经过归类处理,但是部分商品还是存在一定问题,故再次对其进行归类处理。分析归类后各类别商品的销量及其占比,并绘制饼图显示各类商品的销量占比情况,如代码清单所示。
import pandas as pd
inputfile1='../data/GoodsOrder.csv'
inputfile2='../data/GoodsTypes.csv'
data=pd.read_csv(inputfile1,encoding='gbk')
types=pd.read_csv(inputfile2,encoding='gbk') #读入数据
group=data.groupby(['Goods']).count().reset_nindex()
sort=group.sort_values('id',ascending=False).reset_index()data_nums=data.shape[0] #总量
del sort['index']
sort_links=pd.merge(sort,types) #合并两个datafreame根据type
#根据类别求和,每个商品类别的总量,并排序
sort_link=sort_links.
groupby(['Types']).sum().reset_index()
sort_link=sort_link.sort_values('id',ascending=False).reset_index()
del sort_link['index'] #删除"index"列
#求百分比,然后再换列名,最后输出到文件
sort_link['count']=sort_link.apply(lambda line:line['id']/data_nums,axis=1)
sort_link.rename(columns={'count','percent'},inplace=True)
print('各类别商品的销量及其占比:,sort_link)
outfile1='../tmp/percent.csv'sort_link.to_scv(outfile1, index=False,header=True,encoding='gbk') #保存结果
#画饼图展示每类商品销量占比
import matplotlib.pyplot as plt
data=sort_link['percent']
labels=sort_link['Types']
plt.figure(figsize=(8,6)) #设置画布大小
plt.pie(data,labels=labels,autopct='%1.2f%%')
plt.rcParams['font.sans-serif']='SimHei'
plt.savefig('../tmp/persent.png') #把图片以.png格式保存
plt.show()
根据代码清单可得个类别商品的销量及其占比情况,结果如图所示:
商品类别 | 销量 | 销量占比 |
非酒精饮料 | 7594 | 17.51% |
西点 | 7192 | 16.58% |
果蔬 | 7146 | 16.48% |
米粮调料 | 5185 | 11.96% |
百货 | 5141 | 11.85% |
肉类 | 4870 | 11.23% |
酒精饮料 | 2287 | 5.27% |
食品类 | 1870 | 4.31% |
零食 | 1459 | 3.36% |
熟食 | 541 | 1.25% |
根据图表可得,非酒精饮料,西点,果蔬三类商品销量差距不大,占总销量的50%左右,而用数据看可以看得出来食品相关的类的销量总和接近90%,说明了顾客切向于购买此类产品。
进一步查看销量第一的非酒精饮料类商品的内部商品结构,并绘制饼图显示其销量占比情况,如代码清单所示:
#先筛选“非酒精饮料”类型的商品,然后求百分比,然后输出结果到文件。
selected=sort_links.loc[sort_links['Types']=='非酒精饮料'] #挑选商品类别为“非酒精饮料”并排序
child_nums=selected['id'].sum() #对所有的“非酒精饮料”求和
selected['child_percent']=selected.apply(lambda line:line['id']/child_nums,axis=1) #求百分比
selected.rename(columns={'id':'count'},inplace=True)
print('非酒精饮料内部商品的销量及其占比:/n',selected)outfile2='../tmp/child_percent.csv'
sort_link.to_csv(outfile2,index=False,header=True,encoding='gbk') #输出结果
#画饼图展示非酒精饮料内部各商品的销量占比
import matplotlib.pyplot as plt data=selected['child_percent']
labels=selected['Goods']
plt.figure(figsize=(8,6)) #设置画布大小
explode=(0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.08,0.3,0.1,0.3) #设置每一块分割出的间隙大小
plt.pie(data,explode=explode,labels=labels,autopct='%1.2f%%',pctdistance=1.1,labeldistance=1.2)
plt.rcParams['font.sans-serif']='SimHei'
plt.title("非酒精饮料内部各商品的销量占比”) #设置标题
plt.axis('equal')
plt.savefig('../tmp/child_persent.png') #保存图片
plt.show() #展示图形
根据代码可得非酒精饮料内部商品的销量及其占比情况,如表所示:
商品类别 | 销量 | 销量占比 |
全脂牛奶 | 2513 | 33.09% |
苏打 | 1715 | 22.58% |
瓶装水 | 1087 | 14.31% |
水果/蔬菜汁 | 711 | 9.36% |
咖啡 | 571 | 7.52% |
超高温杀菌的牛奶 | 329 | 4.33% |
其他饮料 | 279 | 3.67% |
一般饮料 | 256 | 3.37% |
速溶咖啡 | 73 | 0.96% |
茶 | 38 | 0.50% |
可可饮料 | 22 | 0.29% |
通过表格可以看得出来,全脂牛奶占总比超过33%,前3种非酒精饮料的销量在非酒精饮料的总销量中占比接近70%,说明了大部分顾客到店购买的饮料为这三种,需要时常注意货物的库存,定期补货必不可少。
通过对数据分析,发现数据完整,并不存在缺失值。建模之前需要转变数据的格式,才能使用Apriori函数进行关联分析。对数据进行转换,如代码清单所示:
import pandas as pd inputfile='../data/GoodsOrder.csv'
data=pd.read_csv(inputfile,encoding='gbk')
#根据id对"Goods"列合并,并使用","将各商品隔开
data['Goods']=data['Goods'].apply(lambda x:','+)
data=data.groupby('id').sum().reset_index()
#对合并的商品列转换数据格式
data['Goods']=data['Goods'].apply(lambda x :[x[1:]])
data_list=list(data['Goods'])
#分割商品名为每个元素
data_translation=[]
for i in data_list:
p=i[0].split(',')
data_translation.append(p)
print('数据转换结果的前5个元素:/n',data_translation[0:5])
本案例的目标是探索商品之间的关联关系,因此采用关联规则算法,挖掘它们之间的关联关系。关联规则算法主要用于寻找数据中项集之间的关联关系。它揭示了数据项间的未知关系,基于样本的统计规律,进行关联规则分析。根据所分析的关联关系,可从一个属性的信息来推断另一个属性的信息。当置信度达到某一程度值时,就可以认为规则成立。Apriori是常用的关联规则算法之一,也是最为经典的分析频繁项集的算法,第一次实现在大数据集上可行的关联规则提取的算法。除此之外,还有FP-Tree算法,Eclat算法和灰色关联算法等。
商品购物篮关联规则模型建模流程是:模型主要由输入,算法处理,输出3个部分组成。输入部分包括:建模样本数据的输入;建模参数的输入。算法处理部分是采用Apriori关联规则算法进行处理。输出部分分为采用Apriori关联规则算法进行处理后的结果。
模型具体实现步骤为:首先设置建模参数最小支持度,最小置信度,输入建模样本数据;然后采用Apriori关联规则算法对建模的样本数据进行分析,以模型参数设置的最小支持度,最小置信度以及分析目标作为条件,如果所有的规则都不满足条件,则需要重新调整模型参数,否则输出关联规则结果。
目前如何设置最小支持度与最小置信度,并没有统一的标准。大部分都是根据业务经验设置初始值,然后经过多次调整,获取与业务相符的关联规则结果。本案例经过多次调整结合实际业务分析,选取模型的输入参数为:最小支持度0.02,最小置信度0.35。其关联规则代码如代码清单所示:
form numpy import*
def loadDataSet():
return[['a','c','e'],['b','d'],['b','c'],['a','b','c','d'],['a','b'],['b','c'],['a','b'],['a','b','c','e'],['a','b','c'],['a','c','e']]
def createC1(dataSet):
C1=[]
for transaction in dataSet:
for item in transaction:
if not [item] in C1:
C1.sort()
#映射为frozenset唯一性的,可使用其构造字典
return list(map(frozenset, C1))
#从候选K项集到频繁K项集(支持度计算)
def scanD(D,CK,minSupport):
ssCnt={}
for tid in D:#遍历数据集
for can in CK:#遍历候选项
if can.issubset(tid):#判断候选项中是否含数据集的各项
if not can in ssCnt:
ssCnt[can]=1 #不含设为1
else:
ssCnt[can]+=1 #有则计数加1
numltems =float(len(D)) #数据集大小
retList=[] #L1初始化
supportData={} #记录候选项中各个数据的支持度
for key in ssCnt:
support=ssCnt[key]/numltems #计算支持度
if support>=minSupport:
retList.insert(0,key) #满足条件加入L1中
supportData[key]=support
return retList,supportData
def calSupport(D,CK,minsupport):
dic_sup ={}
for i in D:
for j in CK:
if j.issubset(i):
if not j in dict_sup:
dict_sup[j]=1
else:
dict_sup[j]+=1
sumCount=float(len(D))
supportData={}
relist=[]
for i in dict_sup:
temp_sup=dict_sup[i]/sumCount
if temp_sup>=min_support:
relist.append(i)
#此处可设置返回全部的支持度数据(或者频繁项集的支持度数据)
supportData[i]=temp_sup
return relist,supportData
#改进剪枝算法
def aprioriGen(LK,K):
retList=[]
lenLK=len(LK)
for i in range(lenLK):
for j in range(i+1,lenLK): #两两组合遍历
L1=list(LK[i])[:k-2]
L2=list(LK[j])[:k-2]
L1.sort()
L2.sort()
if L1==L2: #前K-1项相等,则可相乘,这样可防止重复项出现
进行剪枝(a1为K项集中的一个元素,b为它的
运行代码清单得到的结果如下:
frozenset({'水果/蔬菜汁'})-->
frozenset({'全脂牛奶'})支持度0.02664置信度:0.368495 lift值为:1.44216
frozenset({'人造黄油'})-->
frozenset({'全脂牛奶‘})支持度0.024199置信度:0.413194 lift值为:1.617098
... ... ... ...
frozenset({'根茎类蔬菜','其他蔬菜'})-->frozenset({'全脂牛奶'})支持度0.023183置信度:0.48927 lift 值为:1.914833
根据代码清单运行结果,我们得出了26个关联规则。根据规则结果,可整理出购物篮关联规则模型结果,如表所示:
lhs | rhs | 支持度 | 置信度 | lift | |
{'水果/蔬菜汁'} |
=> | {'全脂牛奶’} | 0.02664 | 0.368495 | 1.44216 |
{'人造黄油'} | => | {‘全脂牛奶'} | 0.024199 | 0.413194 | 1.617098 |
{'仁果类水果'} | => | {'全脂牛奶'} | 0.030097 | 0.397849 | 1.557043 |
{'牛肉'} | => | {’全脂牛奶‘} | 0.021251 | 0.405039 | 1.58518 |
{'冷冻蔬菜'} |
=> | {’全脂牛奶‘} | 0.020437 | 0.424947 | 1.663094 |
{'本地蛋类'} | => | {’其他蔬菜‘} | 0.022267 | 0.350962 | 1.813824 |
{'黄油'} | => | {’其他蔬菜‘} | 0.020031 | 0.361468 | 1.868122 |
{'本地蛋类'} | => | {'全脂牛奶’} | 0.029995 | 0.472756 | 1.850203 |
{'黑面包"} | => | {‘全脂牛奶’} | 0.025216 | 0.388715 | 1.521293 |
{'糕点'} | => | {‘全脂牛奶’} | 0.033249 | 0.373714 | 1.462587 |
{'酸奶油'} | => | {‘其他蔬菜’} |
0.028876 | 0.402837 | 2.081924 |
{'猪肉'} | => | {‘其他蔬菜’} | 0.021657 | 0.373714 | 1.941476 |
{'酸奶油'} | => | {‘全脂牛奶’} | 0.032232 | 0.402837 | 1.759754 |
{'猪肉'} | => | {‘全脂牛奶’} | 0.022166 | 0.375661 | 1.504719 |
{'根茎类蔬菜'} | => | {‘全脂牛奶’} | 0.048907 | 0.449645 | 1.756031 |
{'根茎类蔬菜'} | => | {‘其他蔬菜’} | 0.047382 | 0.434701 | 2.246605 |
{'疑乳'} | => | {‘全脂牛奶’} | 0.026131 | 0.400458 | 1.941476 |
{'热带水果'} | => | {‘全脂牛奶’} | 0.042298 | 0.403101 | 1.759754 |
{'柑橘类水果'} | => | {'全脂牛奶‘} | 0.030503 | 0.36855 | 1.504719 |
{'黄油'} | => | {’全脂牛奶‘} | 0.027555 | 0.497248 | 1.759754 |
{'酸奶'} | => | {’全脂牛奶‘} | 0.056024 | 0.401603 | 1.504719 |
{'其他蔬菜'} | => | {’全脂牛奶‘} | 0.074835 | 0.386758 | 1.756031 |
{'其他蔬菜','酸奶'} | => | {’全脂牛奶‘} | 0.022267 | 0.512881 | 2.007235 |
{'全脂牛奶','酸奶'} | => | {’其他蔬菜‘} | 0.0.02667 | 0.397459 | 2.054131 |
{'根茎类蔬菜','全脂牛奶'} | => | {’其他蔬菜‘} | 0.023183 | 0.474012 | 2.44977 |
{'根茎类蔬菜','其他蔬菜'} | => | {’全脂牛奶‘} | 0.023183 | 0.48927 | 1.914833 |
根据表中的输出结果,对其中4条进行解释分析如下:
(1){’其他蔬菜‘,’酸奶‘}=>{’全脂牛奶‘}支持度为2。23%,置信度最大为51.29%。说明同事购买酸奶,其他蔬菜和全脂牛奶这3种商品的概率达51.29%,而这种情况发生的可能性为2.23%。
(2){’其他蔬菜‘}=>{’全脂牛奶‘}支持度最大为7.48%,置信度为38.68%。说明同时购买其他蔬菜和全脂牛奶这2种商品的概率达38.68%,而这种情况发生的可能性为7.48%。
(3){'根茎类蔬菜’}=>{‘全脂牛奶’}支持度为4.89%,置信度为44.87%。说明同时购买根茎类蔬菜和全脂牛奶这三种商品的概率达44.87%,而这种情况发生的可能性为4.89%。
(4){‘根茎类蔬菜’}=>{‘其他蔬菜’}支持度为4.74%,置信度为43.47%。说明同时根茎类蔬菜和其他蔬菜这2种商品的概率达43.47%。而这种情况发生的可能性为4.74%。
综合表6以及输出结果分析,顾客购买酸奶和其他蔬菜的时候会同时购买全脂牛奶,其置信度最大达到51.29%。其他蔬菜,根茎类蔬菜和全脂牛奶同时购买的概率较高。
对于结果,从购买者角度进行分析:现代生活中,大多数购买者为家庭主妇,购买的商品大部分是食品,随着生活质量和健康意识的增加,其他蔬菜,根茎类蔬菜和全脂牛奶均为现代家庭每日饮食所必需品。因此,其他蔬菜,根茎类蔬菜和全脂牛奶同时购买的概率较高符合现代人们的生活健康意识。
模型结果表明顾客购买商品的时候会同时购买全脂牛奶。因此,商场应该根据实际情况将会全脂牛奶放在顾客购买商品的必经之路,或者商场明显位置,为了方便顾客拿取。其他蔬菜,根茎类蔬菜,酸奶油,猪肉,黄油,本地蛋类和多种水果同时购买的概率较高,可以考虑绑捆销售,将这些商品的距离尽量拉近,提升购物体验。
本案例主要结合商品零售购物篮的项目,重点介绍了关联规则算法中Apriori算法在商品零售购物篮分析案例中的应用。过程中详细的分析了商品零售的现状与问题,同时给出某商场的商品零售数据,分析了商品的热销程度,最后通过Apriori算法构建相应模型,并根据模型结果制定销售策略。