**
**
#创建FP树节点
class treeNode():
def __init__(self,nodeName,parentNode,count):
self.nodeName=nodeName
self.parentNode=parentNode
self.childNodes={} #有很多个
self.nextLink=None
self.count=count
def increte(self,count):
self.count+=count
def display(self,level=1):
print(level*"-",self.nodeName,self.count)
for child in self.childNodes.values():
child.display(level+1)
#测试
rootNode=treeNode("fruit",None,9)
rootNode.childNodes["apple"]=treeNode("apple",None,13)
rootNode.childNodes["pear"]=treeNode("pear",None,21)
rootNode.display()
**
**
**
'''
功能:将 新的相似节点添加 头指针对应元素的链表结构的最后
参数说明:
nodeToUpdate:头指针中对应的节点,将 targetNode 添加到它的链表的最后一个元素 nodeLink上
targetNode:要添加的相似节点
'''
def updateHeader(updateNode,targetNode):
#print(updateNode.nextLink)
while updateNode.nextLink!=None:
updateNode=updateNode.nextLink
updateNode.nextLink=targetNode
'''
功能:更新fp树
参数说明:
orderItems:对应一条事务经过筛选后的路径,只保留频繁项,并且排好序
rootTree:要更新的树的根节点
headerTable:头指针表,以备更新 headerTable结构:{k-1频繁项:[次数,指针]}
count:这条事务对应项的出现次数
'''
def updateTree(orderItems,rootTree,headerTable,count):
if orderItems[0] in rootTree.childNodes:
#有该元素时计数值+1
rootTree.childNodes[orderItems[0]].increte(count)
else:
#2.没有时创建相应的节点,并添加到树中,同时还要更新头指针列表,以指向新的节点
rootTree.childNodes[orderItems[0]]=treeNode(orderItems[0],rootTree,count)
#更新头指针表或前一个相似元素项节点的指针指向新节点
if headerTable[orderItems[0]][1]==None:
headerTable[orderItems[0]][1]=rootTree.childNodes[orderItems[0]]
else: #如果指针已经有一个了,则需要重新更新
updateHeader(headerTable[orderItems[0]][1],rootTree.childNodes[orderItems[0]])
#oreredItems如果还有节点,则需继续递归
if len(orderItems)>1:
updateTree(orderItems[1::],rootTree.childNodes[orderItems[0]],headerTable,count)
'''
创建树
参数说明:
dataset:原始事务集
{frozenset({'z'}): 1,
frozenset({'h', 'j', 'p', 'r', 'z'}): 1,
frozenset({'s', 't', 'u', 'v', 'w', 'x', 'y', 'z'}): 1,
frozenset({'n', 'o', 'r', 's', 'x'}): 1,
frozenset({'p', 'q', 'r', 't', 'x', 'y', 'z'}): 1,
frozenset({'e', 'm', 'q', 's', 't', 'x', 'y', 'z'}): 1}
minsup:最小支持度
返回:Fp树、头指针
'''
#创建头指针列表
def craeteHeaderTable(dataSet,minSup=1):
headerTable={} #第一次循环产生结构:{k-1频繁项集:次数} ->下面再循环headerTable,增加一个指向相似元素项指针 {k-1频繁项集:[次数,指针]
for transaction in dataSet:
for item in transaction:
headerTable[item]=headerTable.get(item,0)+dataSet[transaction]
#移除不满足最小支持度的元素项
'''
原python2中可以,但python3中 字典在遍历时不能进行修改,建议转成列表或集合处理
for key in headerTable.keys():
del(headerTable[key])
'''
for key in list(headerTable.keys()):
if headerTable[key]0:
#对频繁项集进行排序
oderItems=[v[0] for v in sorted(localID.items(), key=lambda p:p[1], reverse=True)]
updateTree(oderItems,rootTree,headerTable,count) #更新fp树
return rootTree,headerTable
**
**
#1.定一个函数:加载数据集
def laodSimpleData():
simpleData=[['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 simpleData
#定义一个函数:用于将事务列表转为frozenset,并存为字典,每条记录记值为1
def createInitset(dataSet):
retDict={}
for trans in dataSet:
retDict[frozenset(trans)]=1
return retDict
dataSet=laodSimpleData()
print(dataSet)
transactionDict=createInitset(dataSet)
transactionDict
rootTree,headerTable=createTree(transactionDict)
rootTree.display()
'''
为给定元素项生成一个条件模式基(前缀路径),这通过访问树中包含给定元素项的节点的完成
参数说明:
baseRequenceList:输入的频繁项
treeNode为当前FP树中对应的第一个节点(可在函数外部通过headerTable[basePat][1]获取)
函数返回值:
条件模式基condPats,用一个字典表示,{frozenset(前缀路径):计数值}
'''
def findPrefixPath(baseRequenceList,treeNode):
'''创建路径'''
condPats={}
while treeNode!=None:
prefixPath=[]
ascendTree(treeNode,prefixPath)
if len(prefixPath)>1:
condPats[frozenset(prefixPath[1:])]=treeNode.count
treeNode=treeNode.nextLink
return condPats
'''
函数功能:直接修改prefixPath的值,将当前节点leafNode添加到prefixPath的末尾,然后递归添加其父节点。
返回值:prefixPath就是一条从treeNode(包括treeNode)到根节点(不包括根节点)的路径
调用方法:在主函数findPrefixPath()中再取prefixPath[1:],即为treeNode的前缀路径
'''
def ascendTree(leafNode,prefixPath):
#print(leafNode.nodeName)
if leafNode.parentNode!=None:
prefixPath.append(leafNode.nodeName)
ascendTree(leafNode.parentNode,prefixPath)
#测试 生成条件模式基
print(findPrefixPath('x',headerTable['x'][1]))
print(findPrefixPath('t',headerTable['t'][1]))
print(findPrefixPath('s',headerTable['s'][1]))
'''
用于根据每一个频繁项集basePat,先找到条件模式基,再创建一颗条件fp树
'''
condPatBases=findPrefixPath('t',headerTable["t"][1])
#print(condPatBases)
myCondTree,myHead=createTree(condPatBases,2)
print("根据条件模式基生成的FP树:",myCondTree)
myCondTree.display()
print("这个条件FP树对应的头指针表:",myHead)
'''
输入参数:
inTree和headerTable是由createTree()函数生成的数据集的FP树
minSup表示最小支持度
preFix请传入一个空项集(set([])),将在函数中用于保存当前前缀
fresItemList请传入一个空列表([]),将用来存储生成频繁项集
'''
def mineTree(rootTree,headerTable,minSup,preFix,freqItemList):
#头指针表中的元素项按照频繁度排序,从小到大
bigL=[v[0] for v in sorted(headerTable.items(),key=lambda p:str(p[1]))]
#从底层开始 循环
for basePat in bigL:
#加入频繁项集列表
newFreqSet=preFix.copy()
newFreqSet.add(basePat)
freqItemList.append(newFreqSet)
#递归调用函数来创建条件模式基
conditionPatternBases=findPrefixPath(basePat,headerTable[basePat][1])
#构建条件模式Tree,及头指针列表
myCondTree,myHead=createTree(conditionPatternBases,minSup)
if myHead!=None:
#用于测试
print('conditional tree for:',newFreqSet)
myCondTree.display()
mineTree(myCondTree,myHead,minSup,newFreqSet,freqItemList)
#测试
freqItemList=[]
mineTree(rootTree,headerTable,3,set([]),freqItemList)
kosarak.dat
parsedData=[line.split() for line in open('kosarak.dat').readlines()]
initSet=createInitset(parsedData)
myFPTree,myHeaderTable=createTree(initSet,100000)
myFreqList=[]
mineTree(myFPTree,myHeaderTable,100000,set([]),myFreqList)
myFreqList