给出《Python数据分析与挖掘实战大数据技术丛书》Aprior算法另一种写法

背景

关联规则应用,一般是为了寻求:已知某些项在一定概率下推导出另一项,这样的组合。
当然在数据量比较小的时候,这样的问题可以穷尽的,但是在数据量比较大时,搜索将成为瓶颈。
Aprior算法提出频繁项的子集必须都是频繁,据此设计程序将减少搜索次数。
在看《Python数据分析与挖掘实战大数据技术丛书.pdf》,里面实现的Aprior算法有点烦琐,而且未实现剪切步,有提升空间。
按自己的思路重写了一遍,耗时90ms——>70ms,效率提高22%。

代码

import pandas as pd
import itertools
def find_rule2(d, support, confidence):
    """
        关联规则:Aprior算法
            输入:
            d: 数据样本,pd.DataFrame
                示例:(3条数据)
                    a  b  c  d  e
                0  1  0  1  0  1
                1  0  1  0  1  0
                2  0  1  1  0  0
      support:支持度阈值,0.2 表示 20%
   confidence:置信度阈值,0.3 表示 30%
           
        含 连接步、剪切步
    """
    result = dict() #定义输出结果
    # 最小支持度个数
    lend = len(d)
    support_num  = support*lend

    support_series = d.sum() #支持度序列
    L1 = {(k,):v for k,v in support_series[support_series>=support_num].items()} #L1频繁项集
    # 计算支持度数目
    def getsupport(v):
        return np.sum(d.loc[:,v].sum(axis=1)==len(v))

    LL_all = []
    
    LLn = L1
    k = 0
    
    while len(LLn)>1:
        k += 1
        print("开始第%d轮搜索……"%k)
        print("数目:%d"%len(LLn))
        
        LL_all.append(LLn) 
        
        # 连接步:
        df = pd.DataFrame([dict.fromkeys(key,1) for key in LLn.keys()],index=LLn.keys()).fillna(0)
        LL = {}
        for itemsets in itertools.combinations(df.columns[df.sum()>=k],k+1):
            # 剪切步:可以在这里对itemsets的每一个子集是否在频繁项进行过滤减少查找频率
            if np.sum(df.ix[:,itemsets].sum(axis=1)==k) != k+1:
                continue
            snum = getsupport(itemsets)
            if snum >= support_num:
                LL[itemsets] = snum
                
                # 产生关联规则
                for i in range(1,k+1):
                    for cs  in itertools.combinations(itemsets,i):
                        # 置信度 P(B|A) = P(AB)/P(A)
                        cf = snum/LL_all[i-1][cs]
                        if cf>=confidence:
                            name = "".join(["--".join(cs),"->","--".join(set(itemsets).difference(cs))])
                            result[name] = (snum/lend,cf)
        LLn = LL
    return pd.DataFrame(result).T.rename(columns = {0:"support",1:"confidence"}).sort_values(by=["support","confidence"])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值