Skip to content

Commit 96409b4

Browse files
authored
Add files via upload
1 parent a2846f3 commit 96409b4

File tree

1 file changed

+299
-0
lines changed

1 file changed

+299
-0
lines changed

FP_Growth_Project1/FP_Growth.py

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Created on Sun Aug 5 17:29:40 2018
4+
5+
@author: wzy
6+
"""
7+
# FP树的类定义
8+
class treeNode:
9+
def __init__(self, nameValue, numOccur, parentNode):
10+
# 节点名称
11+
self.name = nameValue
12+
# 节点出现次数
13+
self.count = numOccur
14+
# 不同项集的相同项通过nodeLink连接在一起
15+
self.nodeLink = None
16+
# 指向父节点
17+
self.parent = parentNode
18+
# 存储叶子节点
19+
self.children = {}
20+
# 节点出现次数累加
21+
def inc(self, numOccur):
22+
self.count += numOccur
23+
# 将树以文本形式显示
24+
def disp(self, ind=1):
25+
print(' '*ind, self.name, ' ', self.count)
26+
# 绘制子节点
27+
for child in self.children.values():
28+
# 缩进处理
29+
child.disp(ind + 1)
30+
31+
32+
"""
33+
函数说明:构建FP-tree
34+
35+
Parameters:
36+
dataSet - 需要处理的数据集合
37+
minSup - 最少出现的次数(支持度)
38+
39+
Returns:
40+
retTree - 树
41+
headerTable - 头指针表
42+
43+
Modify:
44+
2018-08-06
45+
"""
46+
def createTree(dataSet, minSup=1):
47+
headerTable = {}
48+
# 遍历数据表中的每一行数据
49+
for trans in dataSet:
50+
# 遍历每一行数据中的每一个数据元素
51+
# 统计每一个字母出现的次数,将次数保存在headerTable中
52+
for item in trans:
53+
# 字典get()函数返回指定键的值,如果值不在字典中返回0。
54+
# 由于dataSet里的每个列表均为frozenset所以每一个列表的值均为1即dataSet[trans]=1
55+
headerTable[item] = headerTable.get(item, 0) + dataSet[trans]
56+
# 遍历headerTable中的每一个字母
57+
# 若headerTable中的字母出现的次数小于minSup则把这个字母删除处理
58+
lessThanMinsup = list(filter(lambda k:headerTable[k] < minSup, headerTable.keys()))
59+
for k in lessThanMinsup: del(headerTable[k])
60+
for k in list(headerTable):
61+
if headerTable[k] < minSup:
62+
del(headerTable[k])
63+
# 将出现次数在minSup次以上的字母保存在freqItemSet中
64+
freqItemSet = set(headerTable.keys())
65+
# 如果没有达标的则返回None
66+
if len(freqItemSet) == 0:
67+
return None, None
68+
# 此时的headerTable中存放着出现次数在minSup以上的字母以及每个字母出现的次数
69+
# headerTable这个字典被称为头指针表
70+
for k in headerTable:
71+
# 保存计数值及指向每种类型第一个元素的指针
72+
headerTable[k] = [headerTable[k], None]
73+
# 初始化tree
74+
retTree = treeNode('Null Set', 1, None)
75+
# 遍历dataSet的每一组数据以及这组数据出现的次数
76+
for tranSet, count in dataSet.items():
77+
localD = {}
78+
# 遍历一组数据中的每一个字母
79+
for item in tranSet:
80+
# 如果这个字母出现在头指针表中
81+
if item in freqItemSet:
82+
# 将这个字母以及它在头指针表中出现的次数存储在localD中
83+
localD[item] = headerTable[item][0]
84+
# localD中存放的字母多于一个
85+
if len(localD) > 0:
86+
# 将字母按照出现的次数按降序排列
87+
ordereItems = [v[0] for v in sorted(localD.items(), key=lambda p:(p[1], p[0]), reverse=True)]
88+
# 对树进行更新
89+
updateTree(ordereItems, retTree, headerTable, count)
90+
# 返回树和头指针表
91+
return retTree, headerTable
92+
93+
94+
"""
95+
函数说明:更新树
96+
97+
Parameters:
98+
items - 将字母按照出现的次数按降序排列
99+
inTree - 树
100+
headerTable - 头指针表
101+
count - dataSet的每一组数据出现的次数,在本例中均为1
102+
103+
Returns:
104+
None
105+
106+
Modify:
107+
2018-08-06
108+
"""
109+
def updateTree(items, inTree, headerTable, count):
110+
# 首先查看是否存在该节点
111+
if items[0] in inTree.children:
112+
# 存在则计数增加
113+
inTree.children[items[0]].inc(count)
114+
# 不存在则新建该节点
115+
else:
116+
# 创建一个新节点
117+
inTree.children[items[0]] = treeNode(items[0], count, inTree)
118+
# 若原来不存在该类别,更新头指针列表
119+
if headerTable[items[0]][1] == None:
120+
# 指向更新
121+
headerTable[items[0]][1] = inTree.children[items[0]]
122+
# 更新指向
123+
else:
124+
updateHeader(headerTable[items[0]][1], inTree.children[items[0]])
125+
# 仍有未分配完的树,迭代
126+
if len(items) > 1:
127+
updateTree(items[1:], inTree.children[items[0]], headerTable, count)
128+
129+
130+
"""
131+
函数说明:更新树
132+
133+
Parameters:
134+
nodeToTest - 需要插入的节点
135+
targetNode - 目标节点
136+
137+
Returns:
138+
None
139+
140+
Modify:
141+
2018-08-06
142+
"""
143+
def updateHeader(nodeToTest, targetNode):
144+
while(nodeToTest.nodeLink != None):
145+
nodeToTest = nodeToTest.nodeLink
146+
nodeToTest.nodeLink = targetNode
147+
148+
149+
"""
150+
函数说明:创建数据集
151+
152+
Parameters:
153+
None
154+
155+
Returns:
156+
simpDat - 返回生成的数据集
157+
158+
Modify:
159+
2018-08-06
160+
"""
161+
def loadSimpDat():
162+
simpDat = [['r', 'z', 'h', 'j', 'p'],
163+
['z', 'y', 'x', 'w', 'v', 'u', 't', 's'],
164+
['z'],
165+
['r', 'x', 'n', 'o', 's'],
166+
['y', 'r', 'x', 'z', 'q', 't', 'p'],
167+
['y', 'z', 'x', 'e', 'q', 's', 't', 'm']]
168+
return simpDat
169+
170+
171+
"""
172+
函数说明:将数据集数据项转换为frozenset并保存在字典中,其值均为1
173+
174+
Parameters:
175+
dataSet - 生成的数据集
176+
177+
Returns:
178+
retDict - 保存在字典中的数据集
179+
180+
Modify:
181+
2018-08-06
182+
"""
183+
def createInitSet(dataSet):
184+
retDict = {}
185+
for trans in dataSet:
186+
fset = frozenset(trans)
187+
retDict.setdefault(fset, 0)
188+
retDict[fset] += 1
189+
# retDict[frozenset(trans)] = 1
190+
return retDict
191+
192+
193+
"""
194+
函数说明:寻找当前非空节点的前缀
195+
196+
Parameters:
197+
leafNode - 当前选定的节点
198+
prefixPath - 当前节点的前缀
199+
200+
Returns:
201+
None
202+
203+
Modify:
204+
2018-08-06
205+
"""
206+
def ascendTree(leafNode, prefixPath):
207+
# 当前节点的父节点不为空
208+
if leafNode.parent != None:
209+
# 当前节点添加入前缀列表
210+
prefixPath.append(leafNode.name)
211+
# 递归遍历所有前缀路线节点
212+
ascendTree(leafNode.parent, prefixPath)
213+
214+
215+
"""
216+
函数说明:返回条件模式基
217+
218+
Parameters:
219+
basePat - 头指针列表中的元素
220+
treeNode - 树中的节点
221+
222+
Returns:
223+
condPats - 返回条件模式基
224+
225+
Modify:
226+
2018-08-06
227+
"""
228+
def findPrefixPath(basePat, treeNode):
229+
condPats = {}
230+
while treeNode != None:
231+
prefixPath = []
232+
# 寻找当前非空节点的前缀
233+
ascendTree(treeNode, prefixPath)
234+
# 如果遍历到前缀路线
235+
if len(prefixPath) > 1:
236+
# 将前缀路线保存入字典
237+
condPats[frozenset(prefixPath[1:])] = treeNode.count
238+
# 到下一个频繁项集出现的位置
239+
treeNode = treeNode.nodeLink
240+
# 返回条件模式基
241+
return condPats
242+
243+
244+
"""
245+
函数说明:递归查找频繁项集
246+
247+
Parameters:
248+
inTree - 初始创建的FP树
249+
headerTable - 头指针表
250+
minSup - 最小支持度
251+
preFix - 前缀
252+
freqItemList - 条件树
253+
254+
Returns:
255+
None
256+
257+
Modify:
258+
2018-08-06
259+
"""
260+
def mineTree(inTree, headerTable, minSup, preFix, freqItemList):
261+
# 从头指针表的底端开始
262+
bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: str(p[1]))]
263+
for basePat in bigL:
264+
# 加入频繁项表
265+
newFreqSet = preFix.copy()
266+
newFreqSet.add(basePat)
267+
# print('finalFrequent Item: ', newFreqSet)
268+
freqItemList.append(newFreqSet)
269+
# 创造条件基
270+
condPattBases = findPrefixPath(basePat, headerTable[basePat][1])
271+
# print('condPattBases: ', basePat, condPattBases)
272+
# 从条件模式来构建条件树
273+
myContTree, myHead = createTree(condPattBases, minSup)
274+
# print('head from conditional tree: ', myHead)
275+
# 挖掘条件FP树,直到条件树中没有元素为止
276+
if myHead != None:
277+
print('conditional tree for: ', newFreqSet)
278+
myContTree.disp(1)
279+
mineTree(myContTree, myHead, minSup, newFreqSet, freqItemList)
280+
281+
if __name__ == '__main__':
282+
# 创建树中的一个单节点
283+
# rootNode = treeNode('pyramid', 9, None)
284+
# 增加一个子节点
285+
# rootNode.children['eye'] = treeNode('eye', 13, None)
286+
# 显示子节点
287+
# rootNode.disp()
288+
# 两个子节点
289+
# rootNode.children['phoenix'] = treeNode('phoenix', 3, None)
290+
# 显示
291+
# rootNode.disp()
292+
simpDat = loadSimpDat()
293+
initSet = createInitSet(simpDat)
294+
myFPtree, myHeaderTab = createTree(initSet, 3)
295+
# print(findPrefixPath('x', myHeaderTab['s'][1]))
296+
# myFPtree.disp()
297+
freqItems = []
298+
mineTree(myFPtree, myHeaderTab, 3, set([]), freqItems)
299+
print(freqItems)

0 commit comments

Comments
 (0)