频繁模式挖掘-Apriori算法
DM实验,写的比较二,好多情况还没有考虑,后续有时间会修改。
开始的时候数据结构没设计好导致写到后面费了很大的劲、不过还好python的列表有起死回生的功效、、、
数据集:database.txt
I1,I2,I5 I2,I4 I2,I3 I1,I2,I4 I1,I3 I2,I3 I1,I3 I1,I2,I3,I5 I1,I2,I3
apriori.py
#coding=utf-8 """ author:messiandzcy apriori.py date:2014.12.3 """ #申请存数据库的矩阵,方便以后遍历 def matrix(num_of_transactions,num_of_items): mat = [['#' for y in range (num_of_items+1)] for x in range(num_of_transactions+1)] return mat #输出数据库矩阵调试 def printf(mat,rows,cols): for i in range(rows): for j in range(cols): print mat[i][j], print #读入文件,将数据库存到列表data里,并格式化输出 def ReadFile(): filename = r'database.txt' try: fp = open(filename,"r") print "Reading File '%s'..." % filename print "%-10s%-10s" % ("TID","Items") pos = 1 #pos记录事务数(行数) MAX_j = 0 #记录项的最大宽度(列数) data = matrix(15,10) #最多15个事务,10个项 for line in fp: string=line.strip("\n") print "%-10d%-10s" % (pos,string) j = 1 #记录项的宽度(列数) for items in string.split(","): data[pos][j]=items #向数据库插入数据 j += 1 if j>MAX_j:MAX_j=j pos += 1 fp.close() #print "pos=%d,j=%d" % (pos,MAX_j) #printf(data,pos,MAX_j) print "Read File Success!\n" return (data,pos,MAX_j) except IOError: print "Read File -->'%s' Failed!" % filename print "File --> '%s' does not exist!" % filename except:#other exceptions print "Other Exceptions!" #将数据库转换成垂直格式的,计数时会很方便 def vertical(mat,rows,cols): #扫描一遍数据库并去掉重复的项 lst = [] #项与整数的一一对应 for i in range(rows): for j in range(cols): lst.append(mat[i][j]) lst=list(set(lst)) #去重 #print len(lst) #再扫描一遍数据库,生成新的vertical数据库 I = [[],[],[],[],[],[],[],[],[],[]] #最多支持10个项,每个项对应一个列表 for i in range(rows): for j in range(cols): if mat[i][j]!="#":I[lst.index(mat[i][j])].append(i) #print lst #print I return (lst,I) #根据项集列表扫描数据库并返回支持计数 def count(itemSet,lst,I): if len(itemSet)==1:return len(I[lst.index(itemSet[0])]) #1-项集的情况 x = itemSet[0] ggg =I[lst.index(x)] #获得首元素对应的数据库I的列表 #求多个集合的交 for y in itemSet: ggg = list(set(ggg)&set(I[lst.index(y)])) #print ggg return len(ggg) #最后交集元素的个数即是支持度计数 #运行apriori算法,lst-->记录去重后的项集列表,I-->记录与lst对应索引的vertical数据库 def apriori(lst,I,min_sup): print "Start to Run Apriori!" #print lst #print I d=[[] for i in range(15)] #假定每次自连接产生的项集个数不超过15 num = 0 #记录项集个数 for x in lst: if x!='#': d[num].append(x) #构造初始项集d,第一次比较特殊,从第二次开始要通过自连接来构造 num += 1 #print count(["I1","I2"],lst,I) #格式化输出初始候选项C1,单独处理,不进循环 print "\nCandidate:#1" print "%-10s%-10s" % ("Items","count") for i in range(15): #i是项集的序号 if d[i]!=[]: print "%-10s%-10d" % ("".join(d[i]),count(d[i],lst,I)) #print d iters=1 #迭代次数 while iters<=7: #开始迭代,第一步,Ck-->Lk,根据最小阈值min_sup来剪枝 print "\n#L%d" %iters print "%-10s%-10s" % ("Items","count") for i in range(15): if len(d[i])==iters: #在频繁k项集中查找 if count(d[i],lst,I)>=min_sup: print "%-10s%-10d" % (",".join(d[i]),count(d[i],lst,I)) else:d[i]=[] #否则剪枝 #print d #迭代第二步,自连接Lk-->Ck+1 new = [] for i in d: if len(i)==iters:new.append(i) #把频繁k项集Lk先挑出来,按顺序装在列表new中 #print "new=" #print new if len(new)==0:break #若已经找不到符合条件的频繁k项集,终止循环! if iters==1: #第一次执行完全连接操作 num = 0 for i in range(len(new)): #i,j是下标序号 for j in range(i+1,len(new)): d[num]=[new[i][0],new[j][0]] #自连接后更新项集列表d num += 1 else: #否则执行真正的自连接操作 tmp = [] for i in range(len(new)): #对于每个项集 #print new[i][0:iters-1] if new[i][0:iters-1] not in tmp: #去重 tmp.append(new[i][0:iters-1]) #把每个项集的前k-1项收集起来-->tmp #print "tmp=" #print tmp num = 0 for j in range(len(tmp)): #对于每个前k-1项 hehe = [] for i in range(len(new)): #扫描项集,提取出前缀和前k-1项一致的项集,后面部分-->hehe if tmp[j]==new[i][0:iters-1]:hehe.append(new[i][iters-1]) #得到hehe之后,开始做完全连接 #print "hehe=" #print hehe for m in range(len(hehe)): #i,j是下标序号 for n in range(m+1,len(hehe)): #print tmp[j]+[hehe[m],hehe[n]] d[num]=tmp[j]+[hehe[m],hehe[n]] #自连接后更新项集列表d num += 1 #print "d=" #print d #return print "\nCandidate:#%d" % (iters+1) print "%-10s%-10s" % ("Items","count") for i in range(15): #i是项集的序号 if len(d[i])==iters+1: print "%-10s%-10d" % (",".join(d[i]),count(d[i],lst,I)) #print d iters += 1 #主函数 (data,pos,MAX_j)=ReadFile() #printf(data,pos,MAX_j) #print "pos=%d,j=%d" % (pos,MAX_j) (lst,I)=vertical(data,pos,MAX_j) #转换 #print lst #print vertical min_sup = 2 #设置最小支持度 apriori(lst,I,min_sup)
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。