《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