學習筆記:【案例】中醫證型關聯規則挖掘


案例來源:《Python數據分析與挖掘實戰》第8章

案例背景與挖掘目標

輸入數據:

挖掘目標:

  1. 借助三陰乳腺癌患者的病理信息,挖掘患者的症狀與中醫證型之間的關聯關系
  2. 對截斷治療提供依據,挖掘潛性證素

分析方法與過程(選擇的原則)

子任務規划

  1. 問卷形式收集原始數據
  2. 數據預處理
  3. 運用關聯規則算法建模
  4. 分析結果,應用到實際業務中

實驗
實現Apriori關聯規則算法

  1. 讀取數據 demo/data/apriori.txt
  2. 離散化操作,將事務集轉換為 0, 1 矩陣
  3. 根據支持度找出頻繁集,直至找到最大頻繁集后停止
  4. 根據置信度得到大於等於置信度的規則,即為Apriori算法所求的關聯規則
  5. 對Apriori算法輸出的規則,編寫過濾函數
  6. (拓展)以上實驗使用聚類進行數據離散化,可嘗試其他離散化方法,如等距、等頻、決策樹、基於卡方檢驗等,比較各個方法的優缺點

代碼存檔:

實驗

import pandas as pd
import os
from __future__ import print_function
from sklearn.cluster import KMeans
import time
dpath = './demo/data/data.xls'
input_data = pd.read_excel(dpath)
input_data.describe()
肝氣郁結證型系數 熱毒蘊結證型系數 沖任失調證型系數 氣血兩虛證型系數 脾胃虛弱證型系數 肝腎陰虛證型系數
count 930.000000 930.000000 930.000000 930.000000 930.000000 930.000000
mean 0.232154 0.214438 0.247039 0.217702 0.227043 0.271739
std 0.078292 0.131887 0.087779 0.079210 0.108064 0.099186
min 0.026000 0.000000 0.067000 0.059000 0.003000 0.016000
25% 0.176250 0.127000 0.185000 0.160000 0.140000 0.188250
50% 0.231000 0.186000 0.236500 0.208500 0.200000 0.273000
75% 0.281750 0.274000 0.291000 0.264000 0.318000 0.352000
max 0.504000 0.780000 0.610000 0.552000 0.526000 0.607000
processedfile = './demo/tmp/data_processed2.xls'
typelabel = {u'肝氣郁結證型系數':'A', u'熱毒蘊結證型系數':'B', u'沖任失調證型系數':'C', u'氣血兩虛證型系數':'D', u'脾胃虛弱證型系數':'E', u'肝腎陰虛證型系數':'F'}
k = 4

keys = list(typelabel.keys())
result = pd.DataFrame()
for i in range(len(keys)):
    print(u'executing "%s" clustering' % keys[i])
    kmodel = KMeans(n_clusters=k, n_jobs=4)
    kmodel.fit(input_data[[keys[i]]].as_matrix())
    
    r1 = pd.DataFrame(kmodel.cluster_centers_, columns=[typelabel[keys[i]]])
    r2 = pd.Series(kmodel.labels_).value_counts()
    r2 = pd.DataFrame(r2, columns=[typelabel[keys[i]] + 'n'])
    r  = pd.concat([r1, r2], axis=1).sort_values(typelabel[keys[i]])
    r.index = [1,2,3,4]
    
    #r[typelabel[keys[i]]] = pd.rolling_mean(r[typelabel[keys[i]]], 2)
    r[typelabel[keys[i]]] = r2.rolling(window = 2, center = False).mean()
    r[typelabel[keys[i]]][1] = 0.0
    result = result.append(r.T)
    
result = result.sort_index()
result.to_excel(processedfile)
executing "肝氣郁結證型系數" clustering
executing "熱毒蘊結證型系數" clustering


/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/ipykernel_launcher.py:14: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  


executing "沖任失調證型系數" clustering
executing "氣血兩虛證型系數" clustering
executing "脾胃虛弱證型系數" clustering
executing "肝腎陰虛證型系數" clustering
def connect_string(x, ms):
    x = list(map(lambda i: sorted(i.split(ms)), x))
    l = len(x[0])
    r = []
    for i in range(len(x)):
        for j in range(i, len(x)):
            if x[i][:l - 1] == x[j][:l - 1] and x[i][l - 1] != x[j][l - 1]:
                r.append(x[i][:l - 1] + sorted([x[j][l - 1], x[i][l - 1]]))
    return r
def find_rule(d, support, confidence, ms=u'--'):
    result = pd.DataFrame(index=['support', 'confidence'])  # 定義輸出結果

    support_series = 1.0 * d.sum() / len(d)  # 支持度序列
    column = list(support_series[support_series > support].index)  # 初步根據支持度篩選
    k = 0

    while len(column) > 1:
        k = k + 1
        print(u'\n正在進行第%s次搜索...' % k)
        column = connect_string(column, ms)
        print(u'數目:%s...' % len(column))
        sf = lambda i: d[i].prod(axis=1, numeric_only=True)  # 新一批支持度的計算函數

        # 創建連接數據,這一步耗時、耗內存最嚴重。當數據集較大時,可以考慮並行運算優化。
        d_2 = pd.DataFrame(list(map(sf, column)), index=[ms.join(i) for i in column]).T

        support_series_2 = 1.0 * d_2[[ms.join(i) for i in column]].sum() / len(d)  # 計算連接后的支持度
        column = list(support_series_2[support_series_2 > support].index)  # 新一輪支持度篩選
        support_series = support_series.append(support_series_2)
        column2 = []

        for i in column:  # 遍歷可能的推理,如{A,B,C}究竟是A+B-->C還是B+C-->A還是C+A-->B?
            i = i.split(ms)
            for j in range(len(i)):
                column2.append(i[:j] + i[j + 1:] + i[j:j + 1])

        cofidence_series = pd.Series(index=[ms.join(i) for i in column2])  # 定義置信度序列

        for i in column2:  # 計算置信度序列
            cofidence_series[ms.join(i)] = support_series[ms.join(sorted(i))] / support_series[ms.join(i[:len(i) - 1])]

        for i in cofidence_series[cofidence_series > confidence].index:  # 置信度篩選
            result[i] = 0.0
            result[i]['confidence'] = cofidence_series[i]
            result[i]['support'] = support_series[ms.join(sorted(i.split(ms)))]

    result = result.T.sort_values(['confidence', 'support'], ascending=False)  # 結果整理,輸出
    print(u'\n結果為:')
    print(result)

    return result
inputfile = './demo/data/apriori.txt' #輸入事務集文件
data = pd.read_csv(inputfile, header=None, dtype = object)

start = time.clock() #計時開始
print(u'\n轉換原始數據至0-1矩陣...')
ct = lambda x : pd.Series(1, index = x[pd.notnull(x)]) #轉換0-1矩陣的過渡函數
b = map(ct, data.as_matrix()) #用map方式執行
c = list(b)
data = pd.DataFrame(c).fillna(0) #實現矩陣轉換,空值用0填充
end = time.clock() #計時結束
print(u'\n轉換完畢,用時:%0.2f秒' %(end-start))
del b #刪除中間變量b,節省內存

support = 0.06 #最小支持度
confidence = 0.75 #最小置信度
ms = '---' #連接符,默認'--',用來區分不同元素,如A--B。需要保證原始表格中不含有該字符

start = time.clock() #計時開始
print(u'\n開始搜索關聯規則...')
find_rule(data, support, confidence, ms)
end = time.clock() #計時結束
print(u'\n搜索完成,用時:%0.2f秒' %(end-start))
轉換原始數據至0-1矩陣...

轉換完畢,用時:0.33秒

開始搜索關聯規則...

正在進行第1次搜索...
數目:276...

正在進行第2次搜索...
數目:947...

正在進行第3次搜索...
數目:41...

結果為:
                    support  confidence
A3---F4---H4       0.078495    0.879518
C3---F4---H4       0.075269    0.875000
B2---F4---H4       0.062366    0.794521
C2---E3---D2       0.092473    0.754386
D2---F3---H4---A2  0.062366    0.753247

搜索完成,用時:2.34秒


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM