• 中医证型关联规则挖掘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'
    转换原始矩阵至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'
    耗时%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'
    开始搜索关联规则...')
    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'
    正在进行第%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'
    结果为:')
    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

  • 相关阅读:
    EditPlus保存文件时不生成其备份文件的方法
    一台电脑同时运行多个tomcat配置方法
    Dom4j写XML
    .....
    编程备忘录
    背包问题
    chrome新版不再支持-webkit-text-size-adjust
    安装grunt需要的grunt插件
    初学web前端
    心情烦躁、、
  • 原文地址:https://www.cnblogs.com/amoor/p/9460647.html
Copyright © 2020-2023  润新知