购物篮算法想必大家并不陌生,随便翻开任何一本数据挖掘的书,开篇都会讲牛奶和啤酒的故事,而购物篮算法中有一个很重要的算法是Aprioi算法,算法详解可见如下链接。
https://blog.csdn.net/baimafujinji/article/details/53456931
在进行Aprioi算法的频繁项集选择时,比较常见的一个操作是从一堆物品集合中挑选出两两组合或者三三组合的这些小集合,其实就类似于从一堆数据中随机选择几个数,并对其进行枚举。
举个例子:葫芦娃一共有"红黄蓝绿橙靛紫"七种颜色,请帮我随机选择两种颜色,请问一共有多少种选择方法,并将其枚举出来,学过一点概率论的同学应该都清楚,这个数字应该等于7*6/(2!)=21种;那如果要随机取三种呢,应该是7*6*5/(3!)=35种,频繁项集的挑选中,这是非常常见的一步,那么问题来了,怎么来进行这个操作呢。
还是需要拿这个图来说明一下,两个元素的集合来自于一个元素的集合,三个元素的集合又来自于两个元素的集合,同理,四个元素的集合又来自于三个元素的集合,最终可知七个元素的集合来自于六个元素的集合并最终可以凑在一起变成葫芦小金刚。
对Aprioi算法的解释很多文章已经写的很清楚,本文仅针对从一堆选项中形成自己想要的几层集合所需要的函数进行说明。如果只是要写到二项集或者三项集,完全可以写两个函数就可以,但你不能保证你的老板不会让你分析到10层或者20层,写20个函数或者20层循环,想着应该是一件很蠢,并且很没有收益的事情,还好python跟C一样,都是可以调用递归函数,也就是说自己可以调用自己,多么美妙的一件事。
话不多说,直接上代码。
#确定颜色集合
color= [['红'],['橙'],['黄'],['绿'],['蓝'],['靛'],['紫']]
#说明,将颜色集合设置成列表套列表的形式,主要在于二项,或者三项以列表形式存贮更为方便
#列表合并函数
def list_merge(listA):
length = len(listA)
listB = []
for i in range(0,length-1):
a = list(listA[i])
for j in range(i+1,length):
b = a + list(listA[j])
set_b = list(set(b))
set_b.sort()
if len(set_b) == len(a)+1 and set_b not in listB:
listB.append(set_b)
return listB
#递归函数
def create_set(listA, num):
if num<=1:
return listA
else:
return create_set(list_merge(listA), num-1)
color_result = create_set(color, num=3)
print(color_result)
##################################
[['橙', '红', '黄'], ['橙', '红', '绿'], ['橙', '红', '蓝'], ['橙', '红', '靛'], ['橙', '紫', '红'], ['红', '绿', '黄'], ['红', '蓝', '黄'], ['红', '靛', '黄'], ['紫', '红', '黄'], ['红', '绿', '蓝'], ['红', '绿', '靛'], ['紫', '红', '绿'], ['红', '蓝', '靛'], ['紫', '红', '蓝'], ['紫', '红', '靛'], ['橙', '绿', '黄'], ['橙', '蓝', '黄'], ['橙', '靛', '黄'], ['橙', '紫', '黄'], ['橙', '绿', '蓝'], ['橙', '绿', '靛'], ['橙', '紫', '绿'], ['橙', '蓝', '靛'], ['橙', '紫', '蓝'], ['橙', '紫', '靛'], ['绿', '蓝', '黄'], ['绿', '靛', '黄'], ['紫', '绿', '黄'], ['蓝', '靛', '黄'], ['紫', '蓝', '黄'], ['紫', '靛', '黄'], ['绿', '蓝', '靛'], ['紫', '绿', '蓝'], ['紫', '绿', '靛'], ['紫', '蓝', '靛']]
该问题的主要解决思路在于对递归函数的调用,同时在对列表函数做好排序、去重的基础之上,确保每次只保留需要的层级,并且可作为下一步操作的输入,在寻找频繁项集中,可利用该函数快速有效地确定不同集合的组成,以及对应的出现次数。