关联规则apriori算法的python实现

学了两天python,想实践下,正好最近在学习数据挖掘,先用python实现下

注:由于后面加了注释,由于编码问题,可能即使是注释,有的环境也不支持汉字的编码,运行报错的话可以将汉字删除后再运行


环境 ubuntu 13.4      python 2


import itertools
import copy

'''
定义全局变量k,即支持度计数k,此k也可以在运行程序之前输入,简单改动即可
'''
k = 2

'''
存储频繁项集的列表
'''
frequenceItem = []


'''
从txt文件dataset.txt里获取事务集
'''
def getDataSet(args):
    f = open(args,'r')
    source = f.readlines()
    f.close()
    dataset = []
    for line in source:
        temp1 = line.strip('\r\n')
        temp2 = temp1.split(',')
        dataset.append(temp2)
    return dataset


'''
初步扫描事务集,从事务集里获取候选1项集
方法的基本思路是:
定义一个集合tmp,将事务集的第一项作为tmp的初始集合
然后扫描事务集,将不在tmp里的数据项加入tmp中
'''
def find_item( dataset ):
    length = len(dataset)
    for i in range(0, length):
        if  i == 0:
            tmp = set(dataset[i])
        tmp.update(set(dataset[i]))
    candidate=list(tmp)
    candidate.sort()
    return candidate

	
	
'''
从候选项集里找出频繁项集,其中num代表频繁num+1项集
如num为0的为从候选1项集里找出频繁1项集
方法基本思路:
1、定义一个支持度列表count
2、对于每一个候选项,依次扫描事务集,如果该项出现在事务集中就将该项对应的count+1、定义一个支持度列表count+1 
3、将每一项的count和k(支持度计数)进行比较,将count小于k的项剔除
'''
def find_frequent( candidate, dataset, num):
    frequence = []
    length = len(candidate)
    count = []
    for i in range(0, length):
        count.append(0)
        count[i] = 0
        if num == 0:
'''
其实不管num为0还是别的值算法应该是一样的,但是由于程序实现上的问题
num为0的时候选项集是一维列表,其它的时候,候选项集是二维列表,
毕竟只是自己写着玩的,python还不熟,牵一发而动全身,懒得改了
'''
            child= set([candidate[i]])
        else:
            child = set(candidate[i])
        for j in dataset:
            parent = set(j)
            if  child.issubset(parent):
                count[i] = count[i]+1
    for m in range(0, length):
        if  count[m] >= k:
            frequence.append(candidate[m])
    return frequence

	
'''
先验定理,剪枝掉不必要的候选n项集
方法思路:
1、依次取出候选项集里的项
2、取出n项集里的n-1项子集
3、如果所有的n-1项集不都都是频繁n-1项集的子集,则删除该候选项集
'''
def pre_test(candidate, num,frequence):
    r_candidate = copy.deepcopy(candidate)
    for each in candidate:
        for each2 in itertools.combinations(each,num):
            tmp= (list(each2))
            tag = 0
            for j in frequence:
                if num == 1:
                    if (tmp[0] == j):
                        tag = 1
                        break
                else:
                    if  tmp == j:
                        tag = 1
                        break
            if  tag == 0:
                r_candidate.remove(each)
                break
    return r_candidate

	
	
'''
通过频繁n-1项集产生候选n项集,并通过先验定理对候选n项集进行剪枝
方法思路:
1、如果是频繁1项集,则通过笛卡尔积产生频繁2项集
2、如果不是频繁一项集,采用F(k-1) * F(k-1)方法通过频繁n-1项集产生候选n项集
注:F(k-1) * F(k-1)方法在我的另一篇关联算法博客上做了理论上的简单介绍,或者也可以直接参看《数据挖掘导论》
'''
def get_candidata( frequence, num ):
    length = len(frequence)
    candidate =[]
    if  num == 1:
        for each in itertools.combinations(frequence,2):
            tmp = list(each)
            tmp3 = []
            tmp3.append(tmp[0])
            tmp3.append(tmp[1])
            candidate.append(tmp3)
    else:
        for i in range(0,length-1):
            tmp1 = copy.deepcopy(frequence[i])
            tmp1.pop(num-1)
            for j in range(i+1, length):
                tmp2 = copy.deepcopy(frequence[j])
                tmp2.pop(num-1)
                if  tmp1 == tmp2:
                    tmp3 = copy.deepcopy(frequence[i])
                    tmp3.append(frequence[j][num-1])
                    candidate.append(tmp3)
    candidate2 = pre_test(candidate, num, frequence)
    return candidate2

	
'''
main程序
'''
if __name__=='__main__':
    dataset = getDataSet('dataset.txt')
    Item = find_item(dataset)
    num = 0
    frequenceItem= []

'''
通过事务集找到频繁项集,直至频繁n项集为空,则退出循环
'''
    while 1:
        if num == 0:
            candidate = Item
        else:
            candidate = get_candidata(frequenceItem[num-1],num)
        frequenceItem.append(find_frequent( candidate, dataset, num))
        if frequenceItem[num] == []:
            frequenceItem.pop(num)
            break
        num = num+1
'''
打印出频繁项集
'''
    for each in frequenceItem:
        print each




目录位置:


编译结果:


事务集合



  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值