关联分析是数据挖掘中的一种常用算法。它包括频繁项集挖掘和关联规则挖掘两个阶段。
频繁模式的挖掘有Apriori算法,还有FP-growth算法。下面的代码是利用Apriori算法挖掘频繁模式,然后找出关联规则的python实现。
#-*-coding: utf-8 -*-
#基于Apriori算法 挖掘频繁模式,找到关联规则
#本程序为利用Apriori算法挖掘频繁模式和关联规则。
#为了挖掘频繁模式,首先扫描数据集,通过最小支持度的约束,构建频繁1项集,然后由频繁k-1项集,构建出频繁k项集
#为了从频繁k项集中挖掘关联规则,先要确定最小置信度的约束,然后找出符合条件的关联规则
#首先,扫描记录,找到满足最小支持度的项集
#函数返回所有频繁项集列表
def loadDataSet():
return [[1,3,4], [2,3,5], [1,2,3,5], [2,5]]
def createC1(dataSet):
#构建频繁1项集,即每个候选项集只包含一个元素
C1 = [] #C1表示频繁1项集
for transaction in dataSet:
for item in transaction:
if [item] not in C1:
C1.append([item])
C1.sort()
return map(frozenset, C1)
def scanD(D, Ck, minSupport):
#计算Ck中的相机在数据集合D中的支持度
#返回满足最小支持度的项集的集合,和所有项集支持度信息的字典
temp = {} #使用map来存储各个项集支持度信息
for tid in D:
for can in Ck:
if can.issubset(tid):
temp[can] = temp.get(can, 0)+1
numItems = float(len(D))
retList = []
supportData = {}
for key in temp:
support = temp[key]/numItems
if support >= minSupport: #如果满足最小置信度,加入retList
retList.insert(0, key)
supportData[key] = support
return retList, supportData
def aprioriGen(Lk, k):
#初始候选集Lk生成频繁k项集
retList = []
lenLk = len(Lk)
#这两个for循环是重点,从k-1项集生成k项集
for i in range(lenLk):
for j in range(i+1, lenLk):
L1 = list(Lk[i])[:k-2]
L2 = list(Lk[j])[:k-2]
L1.sort()
L2.sort()
if(L1==L2):
retList.append(Lk[i]|Lk[j]) #添加上的是两者并起来的元素
return retList
def apriori(dataSet, minSupport = 0.5):
C1 = createC1(dataSet)
D = map(set, dataSet)
#先构建初始频繁项集,即频繁1项集
L1, suppData = scanD(D, C1, minSupport)
L = [L1]
k = 2 #新生成的下一个是频繁2项集,所以k=2
while(len(L[k-2]) > 0):
Ck = aprioriGen(L[k-2], k)
Lk, supK = scanD(D, Ck, minSupport)
suppData.update(supK) #将新的项集的支持度数据加入原来的总支持度字典中
L.append(Lk) #将符合最小支持度要求的项集加入L
k += 1
return L, suppData
#上面是利用Apriori算法挖掘频繁模式集,
#下面是根据频繁项集挖掘关联规则
def calcConf(freqSet, H, supportData, brl, minConf = 0.7):
#计算规则的可信度,返回满足最小可信度的规则。
#freqSet(frozenset):频繁项集
#H(frozenset):频繁项集中所有的元素
#supportData(dic):频繁项集中所有元素的支持度
#brl(tuple):满足可信度条件的关联规则
#minConf(float):最小可信度
prunedH = []
for conseq in H:
conf = supportData[freqSet]/supportData[freqSet-conseq]
if conf >= minConf:
print freqSet - conseq, '-->', conseq, 'conf:', conf
brl.append((freqSet-conseq, conseq, conf))
prunedH.append((conseq))
return prunedH
def rulesFromConseq(freqSet, H, supportData, brl, minConf = 0.7):
#对频繁项集中元素超过2的项集进行合并。
#freqSet(frozenset):频繁项集
#H(frozenset):频繁项集中的所有元素,即可以出现在规则右部的元素
#supportData(dict):所有项集的支持度信息
#brl(tuple):生成的规则
m = len(H[0])
if len(freqSet) > m+1: # 从右边只有一个元素开始,如果还可以往右边加,就使用aprioriGen函数,继续往右边添加元素
#再进行计算,根据置信度添加关联规则。如果右边频繁向大于1,就递归继续进行计算
Hmp1 = aprioriGen(H, m+1)
Hmp1 = calcConf(freqSet, Hmp1, supportData,brl, minConf)
if len(Hmp1)>1:
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
def generateRules(L,supportData, minConf=0.7):
#根据频繁项集和最小可信度生成规则。
#L(list):存储频繁项集
#supportData(dict):存储着所有项集(不仅仅是频繁项集)的支持度
#minConf(float):最小可信度
bigRuleList = []
for i in range(1, len(L)):
for freqSet in L[i]:
H1 = [frozenset([item]) for item in freqSet] #将每个频繁模式集中的元素放入H1中
if i>1: #如果是频繁2项集,可以直接根据置信度直接生成规则。如果频繁3项集及以上,右侧的元素个数就不确定了,所以需要继续传入函数
rulesFromConseq(freqSet, H1, supportData,bigRuleList,minConf)
else:
calcConf(freqSet, H1, supportData, bigRuleList, minConf)
return bigRuleList
if __name__ == '__main__':
# 导入数据集
myDat = loadDataSet()
# 选择频繁项集
L, suppData = apriori(myDat, 0.5)
rules = generateRules(L, suppData, minConf=0.7)
print 'rules:\n', rules