FP-Growth算法之FPTree实现 Python

从retail.dat文件中读取大量的数据,其中每一行代表一条交易记录。

①第一次扫描数据库,得到频繁1项集L1。

②将L1按照支持度递减的顺序进行排列,同时构造链表的头部表。

③第二次扫描数据库,建立FPTree。

④从FPTree的头表HashL1开始,按照每个频繁项的连接遍历FPTree

⑤遍历单个频繁项的链表找到所有前缀路径def PrePath,得到条件模式库ConPatBase

⑥每一次得到条件模式库之前,将符合条件的频繁项集加入到结果列表result中

⑦对于得到的每一个频繁模式库,建立条件FPTree,只要头表head不为空,就递归挖掘条件FPTree

最后挖掘所有的频繁项集保存在result列表中。结果输出包括所有的频繁项集和相应频率。源码如下:

import time
start=time.time()

class TreeNode:# FPTree类
    def __init__(self, key, value, parent):#构造方法
        self.key = key  # 结点key
        self.value = value  # 结点的value
        self.next = None  # 连接key相同的项
        self.parent = parent  # 指向父结点
        self.child = {}  # 保存子结点
    def addValue(self, value):
        self.value += value
#构建FPTree
def FPTree(dataset,flag):
    HashC1 = {}
    HashL1={}
    for trans in dataset:#每一项在记录中出现的次数,保存为value
         for item in trans:
             HashC1[item] = HashC1.get(item, 0) + dataset[trans]#加上原有的value
    for key,value in HashC1.items():
        if value>= flag:
            # HashL1.update({key:value})
            HashL1[key]=value #将其加入到HashL1中
    L1 = set(HashL1.keys())
    if len(L1) == 0:
        return None#如果Lk为空,则退出
    for k in HashL1:
        HashL1[k] = [HashL1[k], None] #初始化链表头结点
    node = TreeNode("root", 1, None) #创建树的根结点
    Node=node #保存树根结点

    for tranSet,count in dataset.items():
        temp = {}#临时空字典
        for item in tranSet:
              if item in L1:#找出每条交易记录中在L1中的项
                  temp[item] = HashL1[item][0]
        if len(temp) >0:#该条交易记录经过剔除且不为空,就按支持度降序排列并插入FPtree中
            order = []  # 建立空列表,保存每条交易记录剔除后降序排列的临时结果
            for n in sorted(temp.items(), key=lambda value: value[1], reverse=True):
                order.append(n[0])
            for n in order:
                node = AddTree(n, node, HashL1, count)
            node = Node
    return HashL1 #返回所有链表头部的字典集合
def AddTree(n, node, HashL1, value):
        if n in node.child:#检查order中的第一项是否存在子结点中
                node.child[n].addValue(value)
        else: #若不存在
                node.child[n] = TreeNode(n, value, node)#创建一个新TreeNode
                if HashL1[n][1] == None:#如果该结点的下一结点为空,则加入
                    HashL1[n][1] = node.child[n]
                else:
                    AddNode(HashL1[n][1], node.child[n])#链表的当前结点和要插入的新结点
        return node.child[n]
def AddNode(CurrentNode, NewNode):
    while (CurrentNode.next != None):  # 找到链表的最后一个结点
        CurrentNode = CurrentNode.next
    CurrentNode.next = NewNode  # 将新结点插入链表末尾

# 条件模式基
def Traverse(CurrentNode, temp): ##从当前结点递归往上查找整棵树,也包括了当前结点
         if CurrentNode.parent != None:#初始根结点的父结点为None
             temp.append(CurrentNode.key)
             Traverse(CurrentNode.parent, temp)

def PrePath(TreeNode):
        ConPatBase = {}  # 保存条件模式库
        while TreeNode != None:
            temp = []
            Traverse(TreeNode, temp)  # 寻找从该结点往上的所有结点的key
            if len(temp) >= 1:#因为temp列表中也包含当前结点故需从第二个元素开始截取
                ConPatBase[frozenset(temp[1:])] = TreeNode.value  # 将当前结点的value赋值给前缀路径的value
            TreeNode = TreeNode.next  # 继续沿着链表寻找下一个
        return ConPatBase

# 递归寻找频繁项集
def FPgrowth(HashL1,flag,FreqSet,result):
        L1 = {}
        for key,value in sorted(HashL1.items(), key=lambda value:value[1][0],reverse=False):
            L1[key]=value[0]  # 保存按value从小到大排列的L1
        for n,value in L1.items(): #从头指针表的底端开始,遍历L1
                 newFreqSet = FreqSet.copy()
                 newFreqSet[n]=L1[n]
                 result.append(newFreqSet)#将符号条件频繁项集加入到结果列表中
                 ConPatBase = PrePath(HashL1[n][1])#遍历key为n的结点对应的链表中的结点对应的前缀路径
                 Head = FPTree(ConPatBase, flag)#递归创建条件FPTree
                 if Head != None: #则递归挖掘条件FPTree
                     FPgrowth( Head, flag, newFreqSet, result)

# minsup=float(input("请输入最小支持度:"))
minsup=0.005
datalist = []#保存数据
tranCount = 0
for t in open('retail.dat').readlines():  # 返回分割后的字符串列表
    line = t.split()
    tranCount += 1  # 记录交易的总数
    datalist.append(list(map(int, line)))
flag=minsup*tranCount
dataset = {}
#将数据列表转为带有value且为1的字典
for trans in datalist:
        dataset[frozenset(trans)] = dataset.get(frozenset(trans), 0) + 1
HashL1 = FPTree(dataset, flag)
result=[] #创建空列表,保存结果
# FreqSet=set()#创建空集合
FreqSet={}
FPgrowth(HashL1, flag, FreqSet, result)
num=0
for itemset in result:
    num+=1
    print(itemset)
print("一共有%d个频繁项"%num)
end=time.time()
print('Running time: %s Seconds'%(end-start))#程序开始到结束的时间

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值