• fp-growth树创建代码及详细注释


    事务集过滤重排:

    QQ图片20190117153000.png
    #FP树节点结构
    class treeNode:
       def __init__(self,nameValue,numOccur,parentNode):
           self.name=nameValue#节点名
           self.count=numOccur#出现次数
           self.nodeLink=None#链接相似的元素
           self.parent=parentNode#当前节点的父节点
           self.children={}#子节点集
        
       #为count增加指定值
       def inc(self,numOccur):
            self.count += numOccur
       #将树以文本方式显示,用于调试
       def disp(self,ind=1):
            print(' '*ind,self.name,' ',self.count)
            for child in self.children.values():
                child.disp(ind+1)
        
    #minSup:最小支持度
    #由于用例中存在出现次数相同的项如t和 y所以每次排序结果可能会不同从而导致最终的FP树有所不同,但应该是等价的
    def createTree(dataSet,minSup=1):
        headerTable={}
        #循环遍历数据集两次
        for trans in dataSet:#trans:事务
            for item in trans:#item:元素
                headerTable[item]=headerTable.get(item,0)+dataSet[trans]#headerTable中已有的次数+事务中出现的1次
        #❶(以下三行) 移除不满足最小支持度的元素项,headerTable中的key即为具体元素
        for k in list(headerTable.keys()):
            if headerTable[k]<minSup:
                del(headerTable[k])
        freqItemsSet=set(headerTable.keys())#转换为集合得到频繁项集(去除重复)
        #❷ 如果没有元素项满足要求, 则退出
        if len(freqItemsSet)==0:return None,None
        #第二次遍历获得头指针表(元素:元素出现次数,相似元素指针)
        for k in headerTable:
            headerTable[k]=[headerTable[k],None]
        retTree=treeNode('Null Set',1,None)#树初始化:空集:1 无父节点
        for tranSet,count in dataSet.items():
            localD={}
            #❸(以下三行) 根据全局频率对每个事务中的元素进行排序
            for item in tranSet:
                if item in freqItemsSet:
                    localD[item]=headerTable[item]#找出所有事务中的频繁项(元素:元素出现次数)集合
            if len(localD)>0:
                orderedItems=[v[0] for v in sorted(localD.items(),key=lambda p:str(p[1]),reverse=True)]
                #❹ 使用排序后的频率项集对树进行填充
                updateTree(orderedItems,retTree,headerTable,count)#orderedItems:事务中删除非频繁项并逆向排序后剩余的元素集合
        return retTree,headerTable
    
    def updateTree(items,inTree,headerTable,count):
        
        if items[0] in inTree.children:#该元素已存在,直接增加出现次数值
            inTree.children[items[0]].inc(count)
        else:
            inTree.children[items[0]] = treeNode(items[0], count, inTree)#不存在,直接添加,使其父节点指向inTree
            if headerTable[items[0]][1]==None:#如果头表目标节点为空,则将其指向inTree
                headerTable[items[0]][1]=inTree.children[items[0]]#更新头表
            else:#头结点指针不为空,则顺着该指针一直找到链表尾部,并将尾节点指针指向新插入节点
                updateHeader(headerTable[items[0]][1],inTree.children[items[0]])#否则,指向新节点(inTree对应孩子节点,逆序排序,后来指向的出现次数变少)
        if len(items)>1:
            #❺ 对剩下的元素项迭代调用updateTree函数                                   
            updateTree(items[1::],inTree.children[items[0]],headerTable,count)#每次调用时从列表中后一个元素开始
    
    #使链表的尾部指向新节点
    def updateHeader(nodeToTest,targetNode):
        while(nodeToTest.nodeLink!=None):
            nodeToTest=nodeToTest.nodeLink
        nodeToTest.nodeLink=targetNode#链接上当前节点 
    
    def loadSimpDat():
        simpDat=[['r','z','h','j','p'],
                 ['z','y','x','w','v','u','t','s'],
                 ['z'],
                 ['r','x','n','o','s'],
                 ['y','r','x','z','q','t','p'],
                 ['y','z','x','e','q','s','t','m']] 
        return simpDat
    
    def createInitSet(dataSet):
        retDict={}
        for trans in dataSet:
            retDict[frozenset(trans)]=1
        return retDict                 

    最终创建的树为(由于存在出现次数相同的元素 如t 和 y,可能会导致每次排序结果不一致从而使最终产生的树结果也不相同,但所有的树都应该是等价的):

    QQ图片20190117153053.png
    来源:本人博客
  • 相关阅读:
    13.字符串压缩算法
    12.字符串全部替换指定文本
    46.数字到字符串的转换
    45.切割字符串并精确分配内存
    44.字符串删除指定字符或者字符串
    11.表达式计算对一串加减乘除带括号进行计算
    43.可变参数实现printf
    关于float与double区别
    float,double与long long哪个更大?
    double 与0比较时有个精度问题,有时需精确到小数点后面几位,例如与>0.0001,而不能与>0比较
  • 原文地址:https://www.cnblogs.com/nerd/p/10297440.html
Copyright © 2020-2023  润新知