python实现fpgrowth ----持续更新

  • 创建FP树的数据结构
class treeNode:    
    def __init__(self,nameValue,numOccur,parentNode):
        self.name = nameValue        
        self.count = numOccur        
        self.nodeLink = None        
        self.parent = parentNode        
        self.children = {}

name为节点元素名称,
count为元素出现的次数,
nodeLink为指向下一个相似节点的指针,默认为None
parent指向父节点的指针,
children指向子节点的字典,以子节点的元素名称为键,以指向子节点的指针为值


def inc(self,numOccur):
    self.count +=numOccur

inc()用于增加节点出现次数值


    def disp(self,ind=1):
        print(' '*ind,self.name,' ',self.count)
        for child in self.child.values():
            child.disp(ind+1)

disp()函数解析:
打印树的结构
前面空着子节点的值,层次感表示子父节点,输出元素名称和元素个数


  • 构建FP树算法
    输入:数据集、最小尺度
    输出:FP树、头指针表
    1.遍历数据集,统计各元素项出现次数,穿件头指针表
    2.移除头指针表中不满足最小值尺度的元素项
    3.第二次遍历数据集,创建FP树。对每个数据集中的项集:
    3.1初始化空FP树
    3.2对每个项集进行过滤和重排序
    3.3使用这个项集跟新FP树,从FP的根节点开始:
    3.3.1如果当前项集的第一个元素项存在于FP树当前节点的子节点的计数值
    3.3.2否则,创建新的子节点,更新头指针表
    3.3.3对当前项集的其余元素项和当前元素项的对应子节点递归

def creatTree(dataSet,minSup=1):
        '''创建FP树'''
        '''第一次遍历数据集,创建头指针表
        头指针表看成是字典,元素加上元素的个数,再增加一个指针指向头部'''
        headerTable = {}
        for trans in dataSet:
            for item in trans:
                headerTable[item] = headerTable.get(item,0)+dataSet[trans]
        #移除不满足最小支持度的元素项
        for k in headerTable.keys():
            if headerTable[k] < minSup:
                del(headerTable[k])
        #空元素集,返回空
        #set()函数,删除iterable的重复元素,无序
        freqItemSet = set(headerTable.keys())
        if len(freqItemSet) ==0:
            return None,None#返回两个的原因在于元素名+元素数
        #增加一个元素项,用于存放指向相似元素项指针
        for k in headerTable:
            headerTable[k] = [headerTable[k],None]#元素个数后缀上指针
        retTree = treeNode('Null Set',1,None)#根节点
        #第二次遍历数据集,创建FP树
        for tranSet,count in dataSet.items():
            localD = {}
            for item in tranSet:
                #freqItemSet中存放满足最小支持度的元素名
                if item in freqItemSet:
                    localD[item] = headerTable[item][0]
            if len(localD)>0:
                orderedItems = [v[0] for v in sorted(localD.items(),key=lambda p:p[1],reverse=True)]#排序

            #更新FP树
            updateTree(orderedItems,retTree,headerTable,count)
            return retTree,headerTable
              

注释:

关于dataSet的注释:
dataSet不是直觉上的集合的list,而是集合的一个字典,以这个集合为键,值部分记录的是这个集合出现的次数
即项集为键,项集出现的次数为值
dataSet[trans]得到该项集出现的次数
for tranSet,count in dataSet.items()表示一个项集和该项集出现的次数
sorted()函数使用
sorted(iterable,cmp,key,reverse)
iterable为可迭代对象
cmp比较函数,有两个参数,参数值都是从可迭代对象中取出,大于则返回1,小于则返回-1,等于则返回0
key主要用来进行比较的元素,只有一个参数,具体的函数的参数就是取自可迭代对象中,指定可迭代对象中的一个元素来进行排序
reverse排序规则,reverse = True降序,reverse = False升序(默认)
返回值为重新排序的列表
lambda函数:
lambda x:function
:左边放原函数的参数,可以有多个参数,用,隔开;
:右边是返回值
其中p取自迭代localD中,而localD中有{(元素名,指针):元素个数}
p[1]表示元素个数,p[0]表示元素名和指针
这里两种,好理解的是只比较值,不用考虑localD的键


#更新树的函数
def updateTree(items,inTree,headerTable,count):
    '''
    items表示排序后的项集
    inTree表示根节点树结构
    headerTable表示头指针表
    count表示项集个数
    '''
    if items[0] in inTree.children:
        inTree.children[items[0],inc(count)]
        #如果项集中第一个元素在根节点树中,那么(name,count),count加1
    else:
        inTree.children[items[0]] =treeNode(items[0],count,inTree)
        #如果没有这个项,那么创建新的节点
        if headerTable[items[0]][1] ==None:
            headerTable[items[0]][1] = inTree.children[items[0]]
        else:
            updateHeader(headerTable[items[0]][1],inTree.children[items[0]])
        #如果头指针表仍指向根节点则转为该新节点,否则更新表头
    if len(items)>1:
        updateTree(items[1::],inTree.children[items[0]],headerTable,count)
        #如果还有元素项,则继续调用updateTree函数

更新指针

    def updateHeader(nodeToTest,targetNode):
        while nodeToTest.nodeLink !=None :
            nodeToTest = nodeToTest.nodeLink 
        nodeToTest.nodeLink = targetNode
        '''
        nodeToTest表示指针
        targetNode表示子节点
        updateHeader函数的作用是将指针转至子节点上
        '''

构造数据集

def createInitSet(dataSet):
    retDict = {}
    for trans in dataSet:
        retDict[frozenset(trans)] = 1
    return retDict

forzenset()生成一个冻结的集合,该集合不能添加或者删除任何元素

你可能感兴趣的:(advancedos)