第11章:使用Apriori算法进行关联分析(计算频繁项集)

本文旨在介绍如何使用Apriori算法进行关联分析,寻找数据集中频繁出现的项集。通过设定最小支持度阈值(0.8),算法能够找出数据中相互关联的物品集合。Apriori原理利用了频繁项集的性质,避免了生成所有可能组合的低效过程,从而高效地确定频繁项集。代码实现进一步展示了这一过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的:找到数据集中事务的关系,如超市中经常一起出现的物品集合,想找到支持度超过0.8的所有项集

概念:

频繁项集:指经常出现在一起的物品集合;

关联规则:指两个物品之间可能存在很强的关系,如一个人买了什么之后很大可能会买另一种东西;

支持度:数据集中包含该项集的记录所占的比例;保留满足最小支持度的项集即为频繁项集;

可信度:针对诸如{尿布}-{葡萄酒}这样的关联规则产生的,定义为支持度({尿布,葡萄酒})/支持度({尿布})

Apriori原理:

想找到支持度超过0.8的所有项集,一般做法是生成所有可能的组合,对每种组合统计其出现的频繁程度,当物品较多时,做法很慢。Apriori帮助减少可能感兴趣的项集数,原理是如果某个项集是频繁的,则它的所有子集也是频繁,但是反过来,如果一个项集是非频繁的,则它的所有超集也是非频繁的。因此该算法从最简单的一个元素开始,计算一个元素的支持度,如果支持度小于最小支持度,则去除该元素;然后将两个元素结合,计算两个元素的支持度,仍然小于最小支持度则去除,以此类推找到所有可能的大于最小支持度的元素组合。

代码:


def apriori(dataSet,minSupport=0.5):
    #创建单个元素列表
    C1=createC1(dataSet)

    #map必须转化为list才能使用
    D=list(map(set,dataSet))

    #去除支持度小于最小支持度的单个元素,返回大于支持度的单个元素列表以及所有元素的支持度
    L1,supportData=scanD(D,C1,minSupport)

    #L是一
import pandas as pd def loadData(): # 加载数据 data = pd.read_excel(';D:\;\;超市销售关联.xlsx';) # , encoding=';utf-8'; inputList = data.values.tolist() # 将表格中的 T 和 F 转换为 商品名称,A——F为商品编号 header = [';A';, ';B';, ';C';, ';D';, ';E';, ';F';, ';G';, ';H';, ';I';, ';J';, ';K';] itemList = [] for item in inputList: cur = [] for i in range(len(item)): if item[i] == ';T';: cur.append(header[i]) itemList.append(cur) return itemList # 生成频繁一项集 def create_C1(data_set): C1 = set() for t in data_set: for item in t: item_set = frozenset([item]) C1.add(item_set) return C1 # 判断是否满足apriori基本性质 def is_apriori(Ck_item, Lksub1): ";";"; 判断频繁候选k项集是否满足Apriori性质 输入: Ck_item: Ck中包含所有频繁项的候选k-项集 Lksub1: Lk-1, 一个包含所有频繁候选(k-1)-项集的集合 输出: True: 满足 False: 不满足 ";";"; for item in Ck_item: sub_Ck = Ck_item - frozenset([item]) if sub_Ck not in Lksub1: return False return True def create_Ck(Lksub1, k): ";";"; 创建Ck,包含所有频繁候选k项集 by Lk-1';s own connection operation. 输入: Lksub1: Lk-1, 包含所有频繁候选(k-1)项集 k: 频繁项集项目编号 输出: Ck: 所有频繁候选k项集 ";";"; Ck = set() len_Lksub1 = len(Lksub1) list_Lksub1 = list(Lksub1) for i in range(len_Lksub1): for j in rangeƑ, len_Lksub1): l1 = list(list_Lksub1[i]) l2 = list(list_Lksub1[j]) l1.sort() l2.sort() if l1[0:k - 2] == l2[0:k - 2]: Ck_item = list_Lksub1[i] | list_Lksub1[j] # pruning if is_apriori(Ck_item, Lksub1): Ck.add(Ck_item) return Ck def generate_Lk_by_Ck(data_set, Ck, min_support, support_data): ";";"; 从Ck中删除不频繁的生成Lk. 输入: data_set: 交易数据库 Ck: 候选k项集 min_support: 最小支持度 support_data: 频繁项集+支持度组成数据字典 输出: Lk: 所有频繁项集. ";";"; Lk = set() item_count = {} for t in data_set: for item in Ck: if item.issubset(t): if item not in item_count: item_count[item] = 1 else: item_count[item] += 1 t_num = float(len(data_set)) for item in item_count: if (item_count[item] / t_num) >= min_support: Lk.add(item) support_data[item] = item_count[item] / t_num return Lk
最新发布
04-03
<think>好的,用户让我看一下他的Python代码,特别是关于Apriori算法实现的部分。他之前可能遇到了问题,比如频繁项集没有正确输出,或者关联规则生成有问题。现在他提供了代码,我需要仔细检查哪里可能出错。 首先,我看到用户导入了pandas,在loadData函数中读取Excel文件。路径里的分号看起来有问题,应该是正常的引号。比如,'D:\\超市销售关联.xlsx',而用户写成了';D:\;\;超市销售关联.xlsx';,这里的分号可能是输入错误,会导致文件无法正确加载。这可能是第一个问题,导致数据加载失败,进而后面的频繁项集为空。 接下来,在loadData函数中,用户将DataFrame转换为列表,然后处理每个item,将'T'转换为对应的商品名称。这里header是A到K,共11个商品编号。循环中检查每个item[i]是否为'T',如果是,就添加header[i]到cur列表中。这部分逻辑看起来没问题,但需要确认Excel中的数据是否正确,是否确实有'T'和'F'的值,否则可能导致itemList为空,进而影响后续处理。 然后,生成频繁一项集的create_C1函数,使用frozenset,这部分应该没问题。但需要确认data_set是否正确传入,即loadData返回的itemList是否正确。 在is_apriori函数中,检查候选项集是否满足Apriori性质。这里遍历每个item,生成子集sub_Ck,然后检查是否在Lksub1中。逻辑正确,但需要确保Lksub1是正确的频繁k-1项集。 create_Ck函数中,用户试图通过连接Lk-1生成Ck。这里有一个明显的语法错误:rangeƑ,应该是range(1, len_Lksub1)。这里的Ƒ可能是拼写错误,导致代码运行时报错。这会导致无法生成Ck,进而无法生成后续的频繁项集。 generate_Lk_by_Ck函数中,计算支持度,筛选出满足最小支持度的项集。这里使用了item_count来统计每个候选项的出现次数,然后除以总交易数得到支持度。这部分逻辑正确,但需要确认min_support是相对支持度还是绝对次数。用户之前的代码中min_support设置为3,但在这里可能被当作相对值处理,需要检查是否一致。 主函数部分,用户可能没有调用生成Lk的循环,或者没有正确迭代生成所有频繁项集。之前的示例中使用的是FP-growth,而这里用户自己实现了Apriori,但可能没有完整的主流程,比如从C1到L1,然后生成C2,再生成L2,直到无法生成为止。缺少这部分循环会导致只生成一项集,而无法生成更高阶的项集。 此外,用户可能没有正确输出频繁项集。之前的错误是未调用显示频繁项集的部分,现在需要检查是否有打印语句或者返回结果。 总结可能的问题点: 1. 文件路径中的分号错误,导致数据无法加载。 2. create_Ck函数中的rangeƑ语法错误,导致代码无法运行。 3. 主流程中缺少生成所有频繁项集的循环,导致只生成一项集。 4. min_support的处理不一致,可能混淆绝对计数和相对比例。 5. 数据预处理是否正确,比如itemList是否正确转换了'T'为商品名称。 6. 是否有正确输出频繁项集的代码部分,比如打印Lk的结果。 需要逐步检查这些部分,修正语法错误,确保数据正确加载,完善Apriori算法的主流程,最后确保频繁项集关联规则都被正确输出。</think>以下是您的代码分析及改进建议,按模块化结构说明: $\boxed{\text{代码问题诊断}}$ 1. **路径格式错误**: ```python pd.read_excel(';D:\;\;超市销售关联.xlsx';) # 错误的分号包围路径 ``` $\rightarrow$ 应改为 `r'D:\超市销售关联.xlsx'` (原始字符串处理反斜杠) 2. **create_Ck函数语法错误**: ```python for j in rangeƑ, len_Lksub1): # 错误符号Ƒ ``` $\rightarrow$ 应改为 `range(1, len_Lksub1)` 3. **Apriori主逻辑缺失**: - 缺少迭代生成$L_k$的循环结构 - 无最终频繁项集输出语句 $\boxed{\text{改进代码}}$ ```python def main(): data = loadData() min_support = 0.2 # 相对支持度 support_data = {} # 主流程 C1 = create_C1(data) L1 = generate_Lk_by_Ck(data, C1, min_support, support_data) L = [L1] k = 2 while True: Ck = create_Ck(L[k-2], k) if not Ck: break Lk = generate_Lk_by_Ck(data, Ck, min_support, support_data) L.append(Lk) k += 1 # 输出所有频繁项集 print("===== 频繁项集及支持度 =====") for key in support_data: print(f"{list(key)} : 支持度 {support_data[key]:.2f}") ``` $\boxed{\text{关键改进说明}}$ 1. **数据加载修正**: ```python data = pd.read_excel(r'D:\超市销售关联.xlsx') ``` - 使用原始字符串避免转义问题 - 移除多余分号 2. **Apriori算法完整性**: - 添加迭代生成$L_k$的循环结构 - 建立完整的 $L_1 \rightarrow C_2 \rightarrow L_2 \rightarrow ...$ 流程 3. **支持度计算标准化**: ```python if (item_count[item] / t_num) >= min_support: # 使用相对支持度 ``` - 原代码`min_support=3`与此处逻辑冲突,需统一为相对值(如0.2) $\boxed{\text{执行验证步骤}}$ 1. 检查控制台是否输出类似结果: ``` ===== 频繁项集及支持度 ===== ['A'] : 支持度 0.35 ['B'] : 支持度 0.28 ['A', 'B'] : 支持度 0.20 ``` 2. 使用小型测试数据集验证(推荐使用蘑菇数据集等标准测试数据) $\boxed{\text{常见错误防范}}$ ```python # 建议在loadData()添加数据校验 def loadData(): ... print(f"成功加载{len(itemList)}条交易记录,首条示例:{itemList[0]}") return itemList # 在create_Ck添加空集合保护 def create_Ck(Lksub1, k): if not Lksub1: return set() ... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值