python Apriori算法1

蹲街弑〆低调 提交于 2020-02-01 04:23:18
#参考Link:https://www.jianshu.com/p/2ee0a247a8cc
#创建一个数据集合
def loadDataSet():
    #return [[1,3,4],[2,3,5],[1,2,3,5],[2,5]]
    return apriori_metadata

# 创建一项集
# 所有元素转换为不可变的字典,放到列表中
def createC1(dataSet):
    c1 = []
    for trans in dataSet:
        for item in trans:
            if not [item] in c1:
                c1.append([item])
    c1.sort()
    # [1,2,3,4,5]
    return list(map(frozenset,c1)) #[{1},{2},{3},{4},{5}]

# 获取满足最小支持度的候选集与其支持度
# 过滤掉不符合支持度的集合
# 返回 频繁项集列表retList 所有元素的支持度字典
# D = [{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]
# Ck 是k项集 example:1-项集 [{1},{2},{3},{4},{5}]
# minSupport最小支持度
def getSetAndSupport(D, Ck, minSupport):
    subSetSupportNum = {}
    for tid in D:
        for oneOfCk in Ck:              #取出k-项集 中一项
            if oneOfCk.issubset(tid):   # 判断can是否是tid的《子集》 (这里使用子集的方式来判断两者的关系)
                if oneOfCk not in subSetSupportNum:    # 统计该值在整个记录中满足子集的次数(以字典的形式记录,frozenset为键)
                    subSetSupportNum[oneOfCk] = 1
                else:
                    subSetSupportNum[oneOfCk] += 1
    #之前是对每一个 集合进行计数  用于计算支持度
    numItems = float(len(D))    # 获取事务数目
    retList = []                # 重新记录满足条件的数据值(即支持度大于阈值的数据)
    supportData = {}            # 每个数据值的支持度
    for subSet in subSetSupportNum:
        support = subSetSupportNum[subSet] / numItems
        if support >= minSupport: # 只是将满足最小支持度的项集插入
            retList.insert(0, subSet)
        supportData[subSet] = support
    return retList, supportData # 排除不符合支持度元素后的元素 每个元素支持度
 
# 连接与剪枝
# 生成所有可以组合的集合
# 频繁项集列表Lk 项集元素个数k  [frozenset({2, 3}), frozenset({3, 5})] -> [frozenset({2, 3, 5})]
# Lk 是k项集
# linkCK和cutCK都其实是K+1项候选    只是为了方便写成linkCK和cutCK
def aprioriGen(Lk, k,supportData,minSupport = 0.06):
    Ck_1 = []
    linkCK = {}
    cutCK = []
    lenLk = len(Lk)
    #连接
    for i in range(lenLk): # 两层循环比较Lk中的每个元素与其它元素
        for j in range(i+1, lenLk):
            #****连接操作****
            Ck_1.append(Lk[i] | Lk[j])  # 求并集   
    linkCK = set(Ck_1)                  # 去除Ck_1中相同的集合
    linkCK = list(linkCK) 
    #剪枝
    for oneOfCk in linkCK: # 两层循环判断 连接后的集合列表  
        flag = 1
        for sup in supportData:
            if supportData[sup] < minSupport:
                if sup.issubset(oneOfCk):
                    flag = 0
        if flag == 1:
            cutCK.append(oneOfCk)
        
    #print(cutCK)
    return cutCK  # 返回频繁项集列表Ck
 
# 封装所有步骤的函数
# 返回 所有满足大于阈值的组合 集合支持度列表
def apriori(dataSet, minSupport = 0.06):
    Data = list(map(set, dataSet)) # 转换列表记录为字典  [{1, 3, 4}, {2, 3, 5}, {1, 2, 3, 5}, {2, 5}]
    C1 = createC1(dataSet)      # 将每个元素转会为frozenset字典    
                                # [frozenset({1}), frozenset({2}), frozenset({3}), frozenset({4}), frozenset({5})]
    supportAll = []             # supportAll 用于保存所有的支持度 用supportData 保存k-项集的支持度 
                                # supportData在aprioriGen的剪枝操作中时候会用到
    L1, supportData = getSetAndSupport(Data, C1, minSupport)    # 过滤数据  获取1-项集  和其对应的支持度
    supportAll.append(supportData)                              #将1-项集加入到支持度的列表中
    L = [L1]                    # L 会存储所有的的项集
    k = 0
    while (len(L[k]) > 0):      # 若仍有满足支持度的集合则继续做关联分析
        print(k,end='\n')
        Ck = aprioriGen(L[k], k, supportData)                            # Ck候选频繁项集 
        Lk, supportData = getSetAndSupport(Data, Ck, minSupport)   # Lk频繁项集
        #supportData.update(supK)                            # 更新字典(把新出现的集合:支持度加入到supportData中)
        supportAll.append(supportData)                      
        L.append(Lk)            # 将Lk 放到 L 列表中
        k += 1  # 每次新组合的元素都只增加了一个,所以k也+1(k表示元素个数)
    return L, supportAll
 
#获取到数据集合
dataSet = loadDataSet()
#Apriori算法  所有满足大于阈值的组合   集合支持度列表
L,suppAll = apriori(dataSet)
for lk in L:
   print(lk)
print()
#打印出所有支持度
for supp in suppAll:
    for sup in supp:
        print(sup,supp[sup])
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!