用python实现Apriori算法
Apriori算法是一种关联规则挖掘算法,用来找频繁项集和关联规则,Apriori算法利用了频繁项集的子集也一定是频繁的这一思想,例如,如果{A,B} 是频繁项集,则 {A}和{B} 也一定是频繁项集
从1到k(k项集)递归查找频繁项集,再用得到的频繁项集生成关联规则
例题
在这里,我用如下一题进行讲述:
提取以下购物篮数据中的频繁项集和强关联规则(参数设置:最小支持度计数 = 4,最小置信度 = 0.6)
事务ID | 购买商品 |
001 | 面包,黄油,尿布,啤酒 |
002 | 咖啡,糖,小甜饼,鲑鱼,啤酒 |
003 | 面包,黄油,咖啡,尿布,啤酒,鸡蛋 |
004 | 面包,黄油,鲑鱼,鸡 |
005 | 鸡蛋,面包,黄油 |
006 | 鲑鱼,尿布,啤酒 |
007 | 面包,茶,糖鸡蛋 |
008 | 咖啡,糖,鸡,鸡蛋 |
009 | 面包,尿布,啤酒,盐 |
010 | 茶,鸡蛋,小甜饼,尿布,啤酒 |
首先我们将数据放入到文件当中,如下:
面包,黄油,尿布,啤酒
咖啡,糖,小甜饼,鲑鱼,啤酒
面包,黄油,咖啡,尿布,啤酒,鸡蛋
面包,黄油,鲑鱼,鸡
鸡蛋,面包,黄油
鲑鱼,尿布,啤酒
面包,茶,糖,鸡蛋
咖啡,糖,鸡,鸡蛋
面包,尿布,啤酒,盐
茶,鸡蛋,小甜饼,尿布,啤酒导入一些需要用到的模块
import pandas as pd
import numpy as np
import itertools读取文件中数据并进行处理
#读取数据并进行编号和转换
def load_dataSet():
#利用pandas读取数据
data = pd.read_csv('test4-1.csv', header=None, sep='\t', encoding='UTF-8')
# print(data.values)
# print('----')
goods = []
goodsList = {}
change_data= []
#对商品进行编号
for key in data.values:
key = key[0]
key = key.split(',')
for i in key:
if i not in goods:
goods.append(i)
for key in range(len(goods)):
goodsList[goods[key]] = key + 1
#输出商品的编号
print('商品编号:', goodsList)
#转换数据
for key in data.values:
key_num = []
key = key[0].split(',')
for i in key:
key_num.append(goodsList[i])
key_num.sort()
change_data.append(key_num)
#输出转换后的数据
print('\n转换后的数据:', change_data)
return goodsList, change_data加载数据并处理的结果如下

算法中需要将商品进行排列组合,代码如下
#separate函数用于将data中的数据进行排列组合,i是组合的大小
def separate(data, i):
a = []
b = []
for k in data:
for j in range(len(k)):
if k[j] not in a:
a.append(k[j])
if i <= len(a):
for k in itertools.combinations(a, i):
b.append(list(k))
return b计算支持度核心算法如下:
#Apriori算法,其中s是最小支持度,data是数据集,data_iter是迭代中的数据集,c是输出的频繁项集,s是频繁项集对应的支持度
def apriori(s_min, data, data_iter, s=[], c=[], i=1):
if len(data_iter) != 0:
goods = separate(data_iter, i)
data_iter = []
for good in goods:
num = 0
for key in data:
if set(good) <= set(key):
num = num + 1
if num >= s_min:
c.append(good)
s.append(num)
data_iter.append(good)
apriori(s_min, data, data_iter, s, c, i=i+1)计算支持度的结果截图如下

计算关联规则的代码如下
#根据频繁项集获取关联规则,c是最小置信度,S是置信度列表,C是频繁项集
def get_associationRules(c, S, C, goodList):
for key in C:
a = []
b = []
if len(key) > 1:
for i in key:
a.append([i])
b.append(list(goodList.keys())[list(goodList.values()).index(i)])
for a_value in a:
a_value_c = S[C.index(a_value)]
key_c = S[C.index(key)]
if key_c/a_value_c >= c:
# print(a_value, ' ---> ', key, ' : ', key_c/a_value_c)
value = list(goodList.keys())[list(goodList.values()).index(a_value[0])]
d = b.copy()
d.remove(value)
print([list(goodList.keys())[list(goodList.values()).index(a_value[0])]],
' ---> ', d, ' : ', key_c/a_value_c)结果如下:

以下是完整代码:
import pandas as pd
import numpy as np
import itertools
#读取数据并进行编号和转换
def load_dataSet():
# , error_bad_lines = False, index_col=0
#利用pandas读取数据
data = pd.read_csv('test4-1.csv', header=None, sep='\t', encoding='UTF-8')
# print(data.values)
# print('----')
goods = []
goodsList = {}
change_data= []
#对商品进行编号
for key in data.values:
key = key[0]
key = key.split(',')
for i in key:
if i not in goods:
goods.append(i)
for key in range(len(goods)):
goodsList[goods[key]] = key + 1
#输出商品的编号
print('商品编号:', goodsList)
#转换数据
for key in data.values:
key_num = []
key = key[0].split(',')
for i in key:
key_num.append(goodsList[i])
key_num.sort()
change_data.append(key_num)
#输出转换后的数据
print('\n转换后的数据:', change_data)
return goodsList, change_data
#Apriori算法,其中s是最小支持度,data是数据集,data_iter是迭代中的数据集,c是输出的频繁项集,s是频繁项集对应的支持度
def apriori(s_min, data, data_iter, s=[], c=[], i=1):
if len(data_iter) != 0:
goods = separate(data_iter, i)
data_iter = []
for good in goods:
num = 0
for key in data:
if set(good) <= set(key):
num = num + 1
if num >= s_min:
c.append(good)
s.append(num)
data_iter.append(good)
apriori(s_min, data, data_iter, s, c, i=i+1)
#separate函数用于将data中的数据进行排列组合,i是组合的大小
def separate(data, i):
a = []
b = []
for k in data:
for j in range(len(k)):
if k[j] not in a:
a.append(k[j])
if i <= len(a):
for k in itertools.combinations(a, i):
b.append(list(k))
return b
#根据频繁项集获取关联规则,c是最小置信度,S是置信度列表,C是频繁项集
def get_associationRules(c, S, C, goodList):
for key in C:
a = []
b = []
if len(key) > 1:
for i in key:
a.append([i])
b.append(list(goodList.keys())[list(goodList.values()).index(i)])
for a_value in a:
a_value_c = S[C.index(a_value)]
key_c = S[C.index(key)]
if key_c/a_value_c >= c:
# print(a_value, ' ---> ', key, ' : ', key_c/a_value_c)
value = list(goodList.keys())[list(goodList.values()).index(a_value[0])]
d = b.copy()
d.remove(value)
print([list(goodList.keys())[list(goodList.values()).index(a_value[0])]],
' ---> ', d, ' : ', key_c/a_value_c)
if __name__ == '__main__':
goodList, data = load_dataSet()
C = []
C1 = []
S = []
#设置最小支持度为4
apriori(4, data, data, S, C)
for value in C:
a = []
for i in value:
a.append(list(goodList.keys())[list(goodList.values()).index(i)])
C1.append(a)
# print('支持度:', S)
# print('频繁项集:', C)
# print(C1)
print('\n频繁项集的支持度')
for i in range(len(C1)):
print(C1[i], '的支持度:', S[i])
#输出关联规则
print('\n关联规则:置信度')
get_associationRules(0.6, S, C, goodList)
















