import numpy as np
import pandas as pd
pip list
dataset = [['苹果','香蕉','橘子'],['榴莲','香蕉','哈密瓜'],['苹果','香蕉','榴莲','哈密瓜'],['橘子','榴莲']]
type(dataset)
dataset
def create_c1(dataset):
"""
函数功能:⽣成第⼀个候选项集c1,每个项集只有1个项
参数说明:
dataset:list,原始数据集
返回:
list(map(frozenset,c1)):frozenset,候选集合c1
"""
c1=[]
for transaction in dataset:
for item in transaction:
if not {item} in c1:
c1.append({item})
c1.sort()
return list(map(frozenset,c1))
create_c1(dataset)
frozenset('苹果')
def create_freq_transaction(dataset,ck,min_support=0.5):
"""
函数功能:⽣成满⾜最⼩⽀持度的频繁项集
参数说明:
dataset:list,原始数据集
ck:frozenset,候选项集
min_support:float,最⼩⽀持度
返回:
support_data:dict,候选项集ck的⽀持度字典(key:候选项, value:⽀持度)
freq_transaction:list,给定min_support下的ck中的频繁项集
注意:如果ck中得不到频繁项集,则返回的是空list
"""
sscnt = {} # 存放项集及频次
for transaction in dataset:
for can in ck: # 候选项集
if can.issubset(transaction):
sscnt[can] = sscnt.get(can,0)+1 # 频次+1
num_transactions = float(len(dataset)) # 事务总量
freq_transaction = [] # 频繁项集,如果ck中得不到频繁项集,则返回的是空list
support_data = {} # 存放项集及支持度
for key in sscnt:
support = sscnt[key]/num_transactions
support_data[key] = support
if support > min_support:
freq_transaction.append(key) # freq_transaction为空说明频繁3项集是不存在的。
return support_data, freq_transaction
c1 = create_c1(dataset)
support_data, freq_transaction = create_freq_transaction(dataset, c1, min_support=0.7)
support_data # 项集支持度字典
freq_transaction # 频繁项集list
def create_ck(freq_k_transaction):
"""
函数功能:由频繁k项集⽣成k+1候选项集。
参数说明:
freq_k_transaction:list,频繁k项集
这里用频繁K项集,而非k项集,体现了先验原理。即如果⼀个项集是频繁的,则它的所有⼦集⼀定也是频繁的。
反之,如果⼀个项集是⾮频繁项集, 那么它的所有超集也是⾮频繁的。
返回:
ck:list,k+1候选项集。
这里不是返回k+1频繁项集,即暂时没有用支持度阈值对结果过滤。
# 特别重要,体现算法原理,节约计算资源。有3个关键点。
1、不是从k候选项集生成k+1候选项集,为什么?答:因为我们的目标是频繁项集,所以非频繁项集能不计算的就不计算,以便节约计算资源。
2、频繁k项集两两组合。为何不是k频繁项集和1-频繁项集两两组合?答:是为了节约计算资源。先验原理告诉我们,这是可行的。
3、只保留k+1候选项集,逐步计算。
"""
ck = [] # k+1候选项集
k = len(freq_k_transaction)
for i in range(k):
for j in range(i+1,k):
t1 = freq_k_transaction[i]
t2 = freq_k_transaction[j]
t = t1|t2
if (not t in ck) and (len(t) == len(freq_k_transaction[0])+1):
ck.append(t)
return ck
c2 = create_ck(freq_transaction)
c2
support_data, freq_transaction = create_freq_transaction(dataset, c2, min_support = 0.5)
support_data # 项集支持度字典
freq_transaction # 频繁项集list,为空说明频繁3项集是不存在的。
c3=create_ck(freq_transaction)
c3
# 为空说明频繁3项集是不存在的。
def apriori(dataset,min_support=0.5):
'''
函数说明:生成大于支持度阈值下的频繁项集,以及所有候选项集及其支持度
参数说明:
dataset:list,原始数据事务集
min_support:float,最⼩⽀持度
返回:
support_data:dict,所有候选项集ck的⽀持度字典(key:候选项, value:⽀持度)
all_freq_transaction:list,给定min_support下的所有频繁项集
'''
c1 = create_c1(dataset) # 生成候选项集
support_data, freq_transaction_1 = create_freq_transaction(dataset,c1,min_support = min_support) # ⽣成满⾜最⼩⽀持度的频繁项集
all_freq_transaction = [freq_transaction_1]
k = 2 #初始化,辅助参数,没有实际意义
while len(all_freq_transaction[-1])>0 : # all_freq_transaction频繁项集 不为空 才执行while循环
ck = create_ck(all_freq_transaction[-1]) # 由频繁k项集⽣成k+1候选项集
support_data_k,freq_transaction_k = create_freq_transaction(dataset,ck, min_support = min_support)
support_data.update(support_data_k) #更新字典,批量增加
all_freq_transaction.append(freq_transaction_k)
k = k+1
return support_data,all_freq_transaction
dataset = [['苹果','香蕉','橘子'],['榴莲','香蕉','哈密瓜'],['苹果','香蕉','榴莲','哈密瓜'],['橘子','榴莲']]
support_data, all_freq_transaction = apriori(dataset, min_support=0.5)
support_data # 项集支持度字典
all_freq_transaction # 频繁项集list,为空说明频繁3项集是不存在的。
# apriori(dataset, min_support=0.7)
# # #注:返回的最后一行是空集合
def create_subset(fromlist, tolist):
'''
函数功能:已知列表fromlist的所有子集,结果保存到tolist,tolist中的元素格式是冻集合。
eg:由k个元素组成的集合,函数计算含有k-1个元素的子集。
参数:
fromlist:list,集合
tolist:list,子集
'''
for i in range(len(fromlist)):
t=[fromlist[i]]
tt=frozenset(set(fromlist)-set(t))
if not tt in tolist:
tolist.append(tt)
tt=list(t)
if len(tt)>1:
create_subset(tt,tolist)
return None
# 给定一集合,计算所有子集。
fromlist=['a','b','c','d']
tolist=[]
create_subset(fromlist, tolist)
tolist
def cal_conf(fre_set, h, support_data, rulelist, min_conf):
'''
函数功能:给定一个频繁项集,得到它子集中所有可能的关联规则,满足置信度阈值的强关联规则保存在rulelist中。
参数说明:
fre_set:频繁项集
h:dict,是fre_set的所有子集集合。
support_data:dict,项集支持度字典
rulelist:tuple,满足置信度阈值的强关联规则元组
min_conf:float,置信度
提升度需大于1
将辅助函数之前,先看下置信度公式
'''
for after in h:
conf = support_data[fre_set] / support_data[fre_set-after] #计算以after为后项以fre_set-after为前项的置信度
lift = support_data[fre_set] / (support_data[fre_set-after] * support_data[after]) # 提升度
# 置信度>规定值且提升度>1
if conf >= min_conf and lift > 1:
print(fre_set-after,'-->',after,'\n',
'前件支持度:',round(support_data[fre_set-after],3),',',
'后件支持度:',round(support_data[after],3),',',
'联合支持度(联合概率):',round(support_data[fre_set],3),',',
'置信度:',round(conf,3),',',
'提升度:',round(lift,3))
rulelist.append((fre_set-after,after, round(conf,3))) #以元组形式保存
return None
def create_rules(support_data, all_freq_transaction, min_conf=0.8):
'''
函数功能:生成给定频繁项集下的所有关联规则项。
参数:
support_data:dict,项集支持度字典
all_freq_transaction:list,频繁项集
min_conf:float,置信度
返回值:
all_rulelist:list。,满足置信度阈值的强关联规则列表
'''
all_rulelist = []
for i in range(1, len(all_freq_transaction)):
for fre_set in all_freq_transaction[i]:
# 求k项集的所有非空子集,1项集,2项集,直到k-1项集,用h表示,为list类型,元素为frozenset类型
fre_list = list(fre_set)
all_subset = []
create_subset(fre_list, all_subset) # 给定一集合,计算集合所有子集。
cal_conf(fre_set, all_subset, support_data, all_rulelist, min_conf) # 给定一个频繁项集,得到它子集中所有可能的关联规则,满足置信度阈值的强关联规则保存在rulelist中
return all_rulelist
dataset = [['苹果','香蕉','橘子'],['榴莲','香蕉','哈密瓜'],['苹果','香蕉','榴莲','哈密瓜'],['橘子','榴莲']]
dataset1 = [['A','B','D'],
['A','C','D', 'E'],
['A','B','D'],
['B','C', 'D'],
['A', 'C']
]
support_data, all_freq_transaction = apriori(dataset1, min_support = 0.2)
print("------项集支持度字典---------")
print(support_data)
print("\n")
print("------满足条件的频繁项集---------")
print(all_freq_transaction)
print("\n")
print("------满足置信度阈值的强关联规则---------")
all_rulelist = create_rules(support_data, all_freq_transaction, min_conf=1.0)
print(all_rulelist)