中醫證型關聯規則挖掘Python代碼【完整】


《Python數據分析與挖掘實戰》這本書槽點慢慢,代碼不全、錯誤、......此類種種。

文章思路還是有點意思的,稍微折騰、補充練習一下,在此分享一下,希望不吝賜教呢~

  1 # -*- coding: utf-8 -*-
  2 """
  3 Created on Tue Aug  7 20:13:46 2018
  4 
  5 @author: Luove
  6 """
  7 
  8 import pandas as pd
  9 import numpy as np
 10 from sklearn.cluster import KMeans
 11 import matplotlib.pyplot as plt
 12 from datetime import date
 13 # from apriori import *
 14 import time  # 計算耗時
 15 import os
 16 
 17 os.chdir('D:/Analyze/Python Matlab/Python/BookCodes/Python數據分析與挖掘實戰/圖書配套數據、代碼/chapter8/demo/code')
 18 
 19 input = '../data/data.xls'
 20 data = pd.read_excel(input)
 21 
 22 # from __future__ import print_function
 23 typelabel = {u'肝氣郁結證型系數': 'A', u'熱毒蘊結證型系數': 'B', u'沖任失調證型系數': 'C', u'氣血兩虛證型系數': 'D', u'脾胃虛弱證型系數': 'E', u'肝腎陰虛證型系數': 'F'}
 24 k = 4
 25 
 26 keys = list(typelabel.keys())
 27 values = list(typelabel.values())
 28 result = pd.DataFrame()
 29 
 30 # if __name__ == '__main__':  #作為模塊導入不運行此代碼塊,作為函數運行則運行代碼塊(此時__name__等於__main__)
 31 for i in range(len(keys)):
 32     print(u'Hi~Man 我正在進行 "%s"的聚類...' % keys[i])
 33     kmodel = KMeans(n_clusters=k, n_jobs=4)
 34     kmodel.fit(data[[keys[i]]].as_matrix())
 35     #         r1=pd.DataFrame(kmodel.cluster_centers_,columns=[typelabel[keys[i]]])
 36     r1 = pd.DataFrame(kmodel.cluster_centers_, columns=[values[i]])  # 聚類中心
 37     r2 = pd.Series(kmodel.labels_).value_counts()  # 各類含樣本量
 38     r2 = pd.DataFrame(r2, columns=[values[i] + 'n'])  # 轉DataFrame 且修改列名
 39     r = pd.concat([r1, r2], axis=1).sort_values(values[i])
 40     r.index = [1, 2, 3, 4]
 41     r[values[i]] = r[values[i]].rolling(2).mean()  # 滾動計算兩個聚類中心均值
 42     r[values[i]][1] = 0.0  # 將第一個空位補上0
 43     result = result.append(r.T)
 44 result = result.sort_index()
 45 
 46 data_ = data[[keys[i] for i in range(len(keys))]]  # 提取要建模的各證型
 47 # 選擇去掉 r2,方便處理
 48 # result_=result[0:len(result):2]
 49 # result_count=result[1:len(result):2]
 50 result_ = result.iloc[::2, :]
 51 result_count = result.iloc[1::2, :]
 52 # data_.iloc[:,1]
 53 
 54 
 55 # 聚類結果 指標值A1、A2、。。。
 56 strabc = pd.DataFrame()
 57 for i in range(len(keys)):
 58     strabcd = [values[i] + '%s' % (j + 1) for j in range(k)]
 59     strabcd = pd.DataFrame(strabcd, columns=[values[i]])  # columns=[values[i]],columns須是list,要轉化加[],[values[]]
 60     strabc = strabc.append(strabcd.T)
 61 ''' strabc
 62     0   1   2   3
 63 A  A1  A2  A3  A4
 64 B  B1  B2  B3  B4
 65 C  C1  C2  C3  C4
 66 D  D1  D2  D3  D4
 67 E  E1  E2  E3  E4
 68 F  F1  F2  F3  F4
 69 '''
 70 ''' result_ 
 71      1         2         3         4
 72 A  0.0  0.167995  0.246969  0.339837
 73 B  0.0  0.153543  0.298217  0.489954
 74 C  0.0  0.202149  0.289061  0.423537
 75 D  0.0  0.172049  0.251583  0.359353
 76 E  0.0  0.153398  0.258200  0.376062
 77 F  0.0  0.179143  0.261386  0.354643  
 78 '''
 79 # 將數值轉化為類別指標,用到的數據
 80 data_.shape  # (930, 6)
 81 result_.shape  # (6, 4)
 82 strabc.shape  # (6, 4)
 83 len(keys)  # 6
 84 
 85 # 轉換值到指標,為避免潛在錯誤,新建一個的DataFrame接收轉換后的指標矩陣
 86 # data_new=pd.DataFrame(columns=[keys[i]+'new' for i in range(data_.shape[1])])
 87 data_new = pd.DataFrame()
 88 # i=0,1,2,3,4,5,6個,從result_行取比較值,和data_/data列值比較,確定值在strabc中找
 89 # j=0,1,2,3,4個,A類中比較時result_行固定i
 90 for i in range(len(result_)):
 91     index1 = data[keys[i]] < result_.iloc[i, 1]
 92     index2 = (result_.iloc[i, 1] < data[keys[i]]) & (data[keys[i]] < result_.iloc[i, 2])
 93     index3 = (result_.iloc[i, 2] < data[keys[i]]) & (data[keys[i]] < result_.iloc[i, 3])
 94     index4 = result_.iloc[i, 3] < data[keys[i]]
 95     # index0=pd.DataFrame()
 96 
 97     # len(index1)
 98     data_n = index1.copy()  # 僅為生成data_n
 99     data_n[index1 == True] = strabc.iloc[i, 0]
100     data_n[index2 == True] = strabc.iloc[i, 1]
101     data_n[index3 == True] = strabc.iloc[i, 2]
102     data_n[index4 == True] = strabc.iloc[i, 3]
103     # set(data_new)
104     data_new = pd.concat([data_new, data_n], axis=1)
105 '''
106 更好的實現划分方法
107 pd.cut
108 '''
109 # data_.iloc[:,data_.shape[1]-1] #最后一列
110 # data_['n']=0
111 # del(data_['n'])#刪去列名為'n'的列
112 # del(data_[data_.columns[data_.shape[1]-1]])#刪去最后一列
113 
114 # 至此,由值轉指標類別工作完畢,下面開始建模apriori
115 data_new.head(5)
116 
117 data_model = pd.concat([data_new, data['TNM分期']], axis=1)
118 
119 start = time.clock()
120 print(u'\n轉換原始矩陣至0-1矩陣...')
121 '''
122 b是ct函數作用到data_model.as_matrix() (930, 7) 矩陣的結果
123 按行展開排成一序列,作為新建Series的index 對應values為1
124 ct函數就是將x按行排成序列作為index 將x值作為index 
125 
126 '''
127 ct = lambda x: pd.Series(1, index=x[pd.notnull(x)])
128 b = map(ct, data_model.as_matrix())  # 依次作用於matrix的每行
129 c = list(b)  # 必須轉成可迭代的list
130 # len(c)    #930
131 # len(c[0]) #7
132 data_model_ = pd.DataFrame(c).fillna(0)  # 將c list轉化為 DataFrame,所有list的index作為列,每行對應index對應值是對應list[i]
133 # DataFrame 每行對應原一條記錄中各證型的出現與否,是就是1,否為0
134 type(data_model_)
135 data_model_.shape  # (930, 28)
136 # 每行是個事務集
137 end = time.clock()
138 print(u'\n耗時%0.2f ' % (end - start))
139 # del b
140 
141 
142 support = 0.06
143 confidence = 0.75
144 ms = '--'
145 start = time.clock()
146 print(u'\n開始搜索關聯規則...')
147 
148 
149 # 自定義連接函數,用於實現L_{k-1}到C_k的連接
150 def connect_string(x, ms):
151     x = list(map(lambda i: sorted(i.split(ms)), x))
152     l = len(x[0])
153     r = []
154     # 生成二項集
155     for i in range(len(x)):
156         for j in range(i, len(x)):
157             #      if x[i][l-1] != x[j][l-1]:
158             if x[i][:l - 1] == x[j][:l - 1] and x[i][l - 1] != x[j][
159                 l - 1]:  # 判斷數字和字母異同,初次取字母數字不全相同(即不同症狀(字母),或同一證型程度不同(數字))
160                 r.append(x[i][:l - 1] + sorted([x[j][l - 1], x[i][l - 1]]))
161     return r
162 
163 
164 # 尋找關聯規則的函數
165 def find_rule(d, support, confidence, ms=u'--'):
166     result = pd.DataFrame(index=['support', 'confidence'])  # 定義輸出結果
167 
168     support_series = 1.0 * d.sum() / len(d)  # 支持度序列
169     column = list(support_series[support_series > support].index)  # 初步根據支持度篩選,符合條件支持度,共 276個index證型
170     k = 0
171 
172     while len(column) > 1:  # 隨着項集元素增多 可計算的column(滿足條件支持度的index)會被窮盡,隨着證型增多,之間的關系會越來越不明顯,(同時發生可能性是小概率了)
173         k = k + 1
174         print(u'\n正在進行第%s次搜索...' % k)
175         column = connect_string(column, ms)
176         print(u'數目:%s...' % len(column))
177         sf = lambda i: d[i].prod(axis=1, numeric_only=True)  # 新一批支持度的計算函數
178         len(d)
179         # 創建連接數據,這一步耗時、耗內存最嚴重。當數據集較大時,可以考慮並行運算優化。
180         # 依次對column每個元素(如[['A1', 'A2'], ['A1', 'A3']]中的['A1', 'A2'])運算,計算data_model_中對應該行的乘積,930個,若['A1', 'A2']二者同時發生為1則此行積為1
181         d_2 = pd.DataFrame(list(map(sf, column)),
182                            index=[ms.join(i) for i in column]).T  # list(map(sf,column)) 276X930  index 276
183 
184         support_series_2 = 1.0 * d_2[[ms.join(i) for i in column]].sum() / len(d)  # 計算連接后的支持度
185         column = list(support_series_2[support_series_2 > support].index)  # 新一輪支持度篩選
186         support_series = support_series.append(support_series_2)
187         column2 = []
188 
189         for i in column:  # 遍歷可能的推理,如{A,B,C}究竟是A+B-->C還是B+C-->A還是C+A-->B?
190             i = i.split(ms)  # 由'A1--B1' 轉化為 ['A1', 'B1']
191             for j in range(len(i)):  #
192                 column2.append(i[:j] + i[j + 1:] + i[j:j + 1])
193 
194         cofidence_series = pd.Series(index=[ms.join(i) for i in column2])  # 定義置信度序列
195 
196         for i in column2:  # 計算置信度序列  如i為['B1', 'A1']
197             # i置信度計算:i的支持度除以第一個證型的支持度,表示第一個發生第二個發生的概率
198             cofidence_series[ms.join(i)] = support_series[ms.join(sorted(i))] / support_series[ms.join(i[:len(i) - 1])]
199 
200         for i in cofidence_series[cofidence_series > confidence].index:  # 置信度篩選
201             result[i] = 0.0  # B1--A1    0.330409  A1--B1    0.470833,絕大部分是要剔除掉的,初次全剔除
202             result[i]['confidence'] = cofidence_series[i]
203             result[i]['support'] = support_series[ms.join(sorted(i.split(ms)))]
204 
205     result = result.T.sort_values(by=['confidence', 'support'],
206                                   ascending=False)  # 結果整理,輸出,先按confidence升序,再在confidence內部按support升序,默認升序,此處降序
207 
208 
209 '''舉個虛假的例子
210             F2--H2
211 support          0
212 confidence       0
213    轉化為
214         support  confidence
215 F2--H2        0           0
216 '''
217 
218 print(u'\n結果為:')
219 print(result)
220 
221 return result
222 
223 find_rule(data_model_, support, confidence, ms)
224 end = time.clock()
225 print(u'\搜索完畢,耗時%0.2f秒' % (end - start))

 

REF:在源代碼基礎上,合並補充,主要供了解函數用。

 源代碼及數據需要可自取:https://github.com/Luove/Data


免責聲明!

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



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