給出《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"])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章