中医证型关联规则挖掘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

posted @ 2018-08-11 18:35  Luove  阅读(3290)  评论(1编辑  收藏  举报