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()函数解析:
打印树的结构
前面空着子节点的值,层次感表示子父节点,输出元素名称和元素个数
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()生成一个冻结的集合,该集合不能添加或者删除任何元素