import numpy #加载数据集 def loadDataSet(): return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]#数组形式 def createC1(dataSet):#构建集合C1,C1是大小为1的所有候选集的集合 C1 = [] for transaction in dataSet:#循环数组的第一维 for item in transaction:#循环数组的第二维 if not [item] in C1:#如果该项在C1中没有,那么把这项加到C1中 C1.append([item]) C1.sort()#然后对C1进行排序 return list(map(frozenset, C1)) # use frozen set so we C1集合被“冰冻”,人为不可改变,可以将这些集合当做字典键值使用 # can use it as a key in a dict #数据集、候选项集Ck,感兴趣项集的最小支持度 def scanD(D, Ck, minSupport): #计算项集的支持度,并过滤掉支持度低于阈值的项集,从而形成频繁项集。Ck的k代表项集的项数 """ 函数说明:该函数用于从大小为1的所有候选项集的集合C1生成频繁项集列表L1,即retList。 数据集:D 候选项集列表:Ck 最小支持度:minSupport 返回值: 频繁项集列表:retList 包含支持度值的字典:supportData """ ssCnt = {}#定义一个空的字典 for tid in D:#统计项集在数据中的出现次数,循环每个数据(每个数据就是每条交易记录) for can in Ck:#循环候选项集Ck中的每一项 if can.issubset(tid):#判断每个候选项集是否是数据集的子集,若是增加计数值,判断can是否是tid的子集 #if not ssCnt.has_key(can): if not can in ssCnt:#统计数量 ssCnt[can] = 1 # 不含设为1 else: ssCnt[can] += 1 # 有则计数加1 numItems = float(len(D))#得到信息总的长度 retList = []#频繁项集列表 supportData = {}#保存项集的支持度,是一个字典。注意:非频繁项集也保存。 for key in ssCnt:#循环统计的数量中的每一项 support = ssCnt[key] / numItems#计算支持度 if support >= minSupport:#判断支持度是否大于最小的支持度 retList.insert(0, key)#满足条件的关键字(can,也就是候选集)加入reList,在列表的首部插入 supportData[key] = support#保存支持度 return retList, supportData#返回保留的频繁项集和频繁项集的支持度 #输入是频繁项集列表Lk与项集元素个数k,输出为Ck #举例来说,该函数以{0}、{1}、{2}作为输入,会生成{0,1},{0,2},{1,2} def aprioriGen(Lk, k): # creates Ck retList = []#定义一个空列表 lenLk = len(Lk)#得到Lk的长度 for i in range(lenLk):#循环Lk中的每一个元素 for j in range(i + 1, lenLk):#两两组合遍历,相当于遍历两两组合所有的可能 # 前k-2项相同时,将两个集合合并 L1 = list(Lk[i])[:k - 2] # 取出两个集合的前k-1个元素 L2 = list(Lk[j])[:k - 2] L1.sort() L2.sort() if L1 == L2: # if first k-2 elements are equal retList.append(Lk[i] | Lk[j]) # set union把这两个集合合并 return retList def apriori(dataSet, minSupport=0.7):#输入数据集和最小支持度 C1 = createC1(dataSet)#得到所有候选集的集合C1 D = list(map(set, dataSet))#把输入数据集变为集合类型 L1, supportData = scanD(D, C1, minSupport)#得到项集的支持度,并过滤掉支持度低于阈值的项集,从而形成频繁项集。 L = [L1] # L用 来存储所有的频繁项集,将已经一些不频繁的过滤掉 k = 2#定义k等于2 while (len(L[k - 2]) > 0):# 一直迭代到项集数目过大而在事务集中不存在这种n项集 Ck = aprioriGen(L[k - 2], k)# 根据频繁项集生成新的候选项集。Ck表示项数为k的候选项集 # ##L[0]其实代表的是C1(项数为1的候选集项),得到C2 Lk, supK = scanD(D, Ck, minSupport) # Lk表示项数为k的频繁项集,supK为其支持度,再进行过滤,得到他们的支持度,对Ck项集支持度小于0.5的进行过滤,丢掉不满足最小支持度要求的项集 supportData.update(supK) # 添加新频繁项集和他们的支持度 L.append(Lk) # 添加新频繁项集和他们的支持度,项数为2的候选集项在L[1]的位置,append k += 1 #最终过滤到L[k],已经全部过滤完, return L, supportData #生成关联规则,函数最后生成一个包含可信度的规则列表,可以基于可信度对他们进行排序 def generateRules(L, supportData, minConf=0.7): # supportData is a dict coming from scanD#三个输入,1频繁项集列表、2包含哪些频繁项集支持数据的字典,3最小可信度阀 # 频繁项集列表、包含那些频繁项集支持数据的字典、 bigRuleList = [] # 存储所有的关联规则最小可信度阈值 for i in range(1, len(L)): # only get the sets with two or more items#只获取有两个或者更多集合的项,从1,即第二个元素开始,L[0]是单个元素的 # 两个及以上的才可能有关联一说,单个元素的项集不存在关联问题 for freqSet in L[i]:#遍历两个元素的项中的每个频繁项集(两个元素的项中有很多频繁项集) H1 = [frozenset([item]) for item in freqSet]#H1代表每个频繁项集中单个的元素 # 该函数遍历L中的每一个频繁项集并对每个频繁项集创建只包含单个元素集合的列表H1 if (i > 1): # 如果频繁项集元素数目超过2,那么会考虑对它做进一步的合并 rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) else:#第一层时,后件数为1 calcConf(freqSet, H1, supportData, bigRuleList, minConf) return bigRuleList#生成一个包含可信度的规则列表 #生成候选规则集合:计算规则的可信度以及找到满足最小可信度要求的规则 def calcConf(freqSet, H, supportData, brl, minConf=0.7):#输入:某一个频繁项集;包含该频繁项集单个元素的列表;所有频繁项集的支持度;存储最小可信度;最小可信度阈值 # 针对项集中只有两个元素时,计算可信度 prunedH = [] # create new list to return创建一个空列表 #返回一个满足最小可信度要求的规则列表 for conseq in H:#后件,遍历 H中的所有项集并计算它们的可信度值 if (freqSet - conseq) != frozenset(): conf = supportData[freqSet] / supportData[freqSet - conseq] # calc confidence#可信度计算,结合支持度数据,计算conseq的可信度 if conf >= minConf: print(freqSet - conseq, '-->', conseq, 'conf:', conf)#以可信度的表达形式进行表达 # 如果某条规则满足最小可信度值,那么将这些规则输出到屏幕显示 brl.append((freqSet - conseq, conseq, conf))#添加到规则里,brl 是前面通过检查的 bigRuleList,分别把左边右边存储到里面 prunedH.append(conseq)#同样需要放入列表到后面检查 return prunedH def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):#输入:某一个频繁项集;包含该频繁项集单个元素的列表(一个集合);所有频繁项集的支持度;存储最小可信度;最小可信度阈值 # 参数:一个是频繁项集,另一个是可以出现在规则右部的元素列表 H m = len(H[0]) if (len(freqSet) > (m + 1)): # try further merging #频繁项集元素数目大于单个集合的元素数 Hmp1 = aprioriGen(H, m + 1) # create Hm+1 new candidates #存在不同顺序、元素相同的集合,合并具有相同部分的集合 Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)#计算可信度 if (len(Hmp1) > 1): # need at least two sets to merge # 满足最小可信度要求的规则列表多于1,则递归来判断是否可以进一步组合这些规则,循环调用使得Html(即规则右边的元素的个数变为1) rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf) from time import sleep from votesmart import votesmart votesmart.apikey = '14fc970964e42f6eac640f4531f000b5' #使用自己的key # votesmart.apikey = 'get your api key first' # 收集美国国会议案中action ID的函数 def getActionIds(): actionIdList = []#创建两个空列表来返回actionId和标题 billTitleList = [] fr = open('recent20bills.txt')#打开文件 for line in fr.readlines():#读取每一行 billNum = int(line.split('\t')[0])#用制表符进行划分,# 得到了议案的ID try: billDetail = votesmart.votes.getBill(billNum) # api call 用getBill方法获得 for action in billDetail.actions: if action.level == 'House' and \ (action.stage == 'Passage' or action.stage == 'Amendment Vote'):#passage阶段与Amendment Vote阶段都会有投票数据,行政级别上也有一个passage, # 但那个阶段不包含任何投票,所以要确保passage阶段发生在众议院 actionId = int(action.actionId)#取整 print('bill: %d has actionId: %d' % (billNum, actionId)) actionIdList.append(actionId)#附加到列表之中 billTitleList.append(line.strip().split('\t')[1]) except:#调用发生错误 print("problem getting bill %d" % billNum) sleep(1) # delay to be polite return actionIdList, billTitleList
命令窗口:
import apriori import numpy from votesmart import votesmart dataSet=apriori.loadDataSet() print(dataSet) C1=apriori.createC1(dataSet) print('C1=', C1) D=list(map(set,dataSet)) print('D=', D) L1,suppData0=apriori.scanD(D,C1,0.5) print('L1=',L1) print('suppData0=',suppData0) L,suppData=apriori.apriori(dataSet) print(L) L,suppData=apriori.apriori(dataSet,minSupport=0.5) rules=apriori.generateRules(L,suppData,minConf=0.5) print(rules) mushDatSet=[line.split() for line in open('mushroom.dat').readlines()] L,suppData=apriori.apriori(mushDatSet,minSupport=0.3) for item in L[1]: if item.intersection('2'):print(item) print(L) #votesmart.apikey='14fc970964e42f6eac640f4531f000b5' actionIdList,billTitles=apriori.getActionIds()
备注:美国国会投票部分,votesmart出现问题,一直未解决。待后续解决。