《python数据分析与挖掘实战》第八章详解
代碼來自書上,進行了一定修改,確保運行沒有error
挖掘的總體思路:
首先癌癥有不同的發(fā)展期
不同發(fā)展期的癌癥有不同的癥型
這些癥狀都處于不同的嚴(yán)重程度。
因此收集病人樣本930條。
數(shù)據(jù)挖掘流程:
一(對應(yīng)代碼1)、
每人的6種癥型(癥狀名字的代號是A~F,分別對應(yīng)data.xls中的各種癥型)都處于不同的嚴(yán)重程度,
每種癥型按照嚴(yán)重程度高低,聚類為四個區(qū)間,并分別得到各個區(qū)間的數(shù)量。每個區(qū)間取名字例如:A1~A4
由于每個病人都有六種癥狀的不同區(qū)間,因此每個病人都可以由一個6維矢量來表示
二(對應(yīng)代碼2)、6維矢量擴充成24維矢量,使用Apriori算法,找出不同嚴(yán)重程度的癥狀和乳腺癌發(fā)展時期之間的聯(lián)系,也就是說,找出哪些癥狀(例如A3和B5)極有可能導(dǎo)致乳腺癌的某個特定的時期(例如H5),挖掘結(jié)束。
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆第一部分代碼開始☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
# -*- coding: utf-8 -*-
'''
聚類離散化,最后的result的格式為:
? 1 2 3 4
A 0 0.178698 0.257724 0.351843
An 240 356.000000 281.000000 53.000000
即(0, 0.178698]有240個,(0.178698, 0.257724]有356個,依此類推。
'''
from __future__ import print_function
import pandas as pd
from sklearn.cluster import KMeans # 導(dǎo)入K均值聚類算法
datafile = '../data/data.xls' #待聚類的數(shù)據(jù)文件
processedfile = '../tmp/data_processed.xls' # 數(shù)據(jù)處理后文件
typelabel = {u'肝氣郁結(jié)證型系數(shù)': 'A', u'熱毒蘊結(jié)證型系數(shù)': 'B', u'沖任失調(diào)證型系數(shù)': 'C', u'氣血兩虛證型系數(shù)': 'D', u'脾胃虛弱證型系數(shù)': 'E', u'肝腎陰虛證型系數(shù)': 'F'}
k = 4 # 需要進行的聚類類別數(shù)
# 讀取數(shù)據(jù)并進行聚類分析
data = pd.read_excel(datafile) # 讀取數(shù)據(jù)
keys = list(typelabel.keys())
result = pd.DataFrame()
if __name__ == '__main__': # 判斷是否主窗口運行,如果是將代碼保存為.py后運行,則需要這句,如果直接復(fù)制到命令窗口運行,則不需要這句。
? for i in range(len(keys)):#每輪循環(huán)處理一個癥狀的聚類和數(shù)量統(tǒng)計
? print("i=", i)
? # 調(diào)用k-means算法,進行聚類離散化
? print(u'正在進行“%s”的聚類...' % keys[i])
? kmodel = KMeans(n_clusters=k, n_jobs=4) # n_jobs是并行數(shù),一般等于CPU數(shù)較好
? kmodel.fit(data[[keys[i]]].as_matrix()) # 訓(xùn)練模型
? r1 = pd.DataFrame(kmodel.cluster_centers_, columns=[typelabel[keys[i]]]) # 聚類中心
? print("r1=",r1)
? print("label=", typelabel[keys[i]])
? #
? #
? #
? r2 = pd.Series(kmodel.labels_).value_counts() # 分類統(tǒng)計
? print("r2=",r2)
? print("-------------------------------------")
? r2 = pd.DataFrame(r2, columns=[typelabel[keys[i]] + 'number']) # 轉(zhuǎn)為DataFrame,記錄各個類別的數(shù)目
? print("r2=", r2)#這一段用來統(tǒng)計聚類中各個類別的數(shù)量,并且寫入一列中,并改改名字
? #
? #
? #
? #
? r=pd.concat([r1, r2], axis=1)
? print("排序前r=",r)
? r=r.sort_values(typelabel[keys[i]])
? print("排序后r=",r)
? r.index = [1, 2, 3, 4]#index指的是列標(biāo)簽,typelabel[keys[i]]指的是行標(biāo)簽
? #
? #
? #
? #
? print("----------------------------------------------------")
? print("計算均值前的表格r=",r)
? r[typelabel[keys[i]]] = pd.rolling_mean(r[typelabel[keys[i]]], 2) # rolling_mean()用來計算相鄰2列的均值,以此作為邊界點。
? r[typelabel[keys[i]]][1] = 0.0 # 這兩句代碼將原來的聚類中心改為邊界點.這里的用法類似于C語言中的r[i][j]
? print("計算均值后的表格r=",r)
? result = result.append(r.T)#旋轉(zhuǎn)
? print("----------------------------------------------------")
? #
? #
? #
? #
? print("result=",result)
? result = result.sort_index() # 以Index排序,即以A,B,C,D,E,F順序排,A代表癥狀的名稱,BCDE各自代表該癥狀的嚴(yán)重程度
? result.to_excel(processedfile)
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆第一部分代碼結(jié)束☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
輸出的結(jié)果是:
1 2 3 4
A 0 0.178697589 0.2577240643 0.3518431814
Anumber 240 356 281 53
B 0 0.1507662277 0.2966313131 0.4897045019
Bnumber 325 396 180 29
C 0 0.2021487293 0.2890611377 0.4235365546
Cnumber 297 394 204 35
D 0 0.1765046363 0.2571199525 0.3661899988
Dnumber 309 371 211 39
E 0 0.1526978022 0.2575413223 0.3748694473
Enumber 273 319 242 96
F 0 0.1791433755 0.2613863944 0.354642668
Fnumber 200 237 265 228
Dnumber表示D癥狀對應(yīng)的病人樣本數(shù)量
相關(guān)解釋:
axis=0#表格縱軸
axis=1#表格橫軸
每種癥狀都有四個量化區(qū)間
------------------------------------重點代碼解釋1-----------------------------------------
? r=pd.concat([r1, r2], axis=1).sort_values(typelabel[keys[i]])
這里首先是把r1代表的癥狀嚴(yán)重程度的量化參數(shù)(也就是聚類中心)和各個聚類中心對應(yīng)的分類數(shù)量各自整合成一行,如下,
? A Anumber
0 0.220441 356
1 0.136954 240
2 0.408679 53
3 0.295007 281
然后按行排序(這里的行也就是最終結(jié)果中的列,因為后面的代碼中存在轉(zhuǎn)置)
? A Anumber
1 0.136954 240
0 0.220441 356
3 0.295007 281
2 0.408679 53
axis=1#表示按行的意思
------------------------重點代碼解釋1----------------------------------------------------
------------------------------------重點代碼解釋2---------------------------------------------------------------------------
?r[typelabel[keys[i]]] = pd.rolling_mean(r[typelabel[keys[i]]], 2) # rolling_mean()用來計算相鄰2列的均值,以此作為邊界點。
解釋下這里的r1和r2如何組合成r
舉例,輸出的其中一段結(jié)果為:
計算均值前的表格r= C Cnumber
1 0.158734 297
2 0.245563 394
3 0.332559 204
4 0.514514 35
計算均值后的表格r= C Cnumber
1 0.000000 297
2 0.202149 394
3 0.289061 204
4 0.423537 35
(0.245563+0.332559)/2=0.289061?
自己評論:這種處理方式并不合理,因為數(shù)據(jù)是對應(yīng)于聚類中心的,作者在這里隨意利用聚類中心進行計算得到的區(qū)間,顯然是和分類數(shù)量在意義和實際上都是不對應(yīng)的。
-----------------------------重點代碼解釋2--------------------------------------------------------
--------------------------后續(xù)處理-------------------------------------------------
得到聚類處理后的文件為data_processed.xls
結(jié)合輸入文件data.xls
由于得到了每種癥狀的各種嚴(yán)重程度的量化區(qū)間,所以把data.xls中的各個參數(shù)(例如A癥狀)轉(zhuǎn)化為A1~A4
轉(zhuǎn)化辦法如下:
data.xls中,對每行的首單元進行按行排序,由于data.xls中第一列的各項數(shù)據(jù)處于data_processed.xls的四個區(qū)間中,
分別改為A1~A4,從而得到下一份代碼需要的文件apriori.txt文件
-------------------------------后續(xù)處理結(jié)束--------------------------------------------
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆接下來是第二部分☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
被調(diào)用函數(shù)apriori.py如下
#-*- coding: utf-8 -*-
from __future__ import print_function
import pandas as pd
#自定義連接函數(shù),用于實現(xiàn)L_{k-1}到C_k的連接
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
#尋找關(guān)聯(lián)規(guī)則的函數(shù)
def find_rule(d, support, confidence, ms = u'--'):
? result = pd.DataFrame(index=['support', 'confidence']) #定義輸出結(jié)果
? support_series = 1.0*d.sum()/len(d) #支持度序列
? column = list(support_series[support_series > support].index) #初步根據(jù)支持度篩選
? k = 0
? while len(column) > 1:
? k = k+1
? print(u'\n正在進行第%s次搜索...' %k)
? column = connect_string(column, ms)
? print(u'數(shù)目:%s...' %len(column))
? sf = lambda i: d[i].prod(axis=1, numeric_only = True) #新一批支持度的計算函數(shù)
? #創(chuàng)建連接數(shù)據(jù),這一步耗時、耗內(nèi)存最嚴(yán)重。當(dāng)數(shù)據(jù)集較大時,可以考慮并行運算優(yōu)化。
? d_2 = pd.DataFrame(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) #結(jié)果整理,輸出
? print(u'\n結(jié)果為:')
? print(result)
? return result
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆第2部分代碼開始☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
#-*- coding: utf-8 -*-
from __future__ import print_function
import pandas as pd
from apriori import * #導(dǎo)入自行編寫的apriori函數(shù)
import time #導(dǎo)入時間庫用來計算用時
inputfile = '../data/apriori.txt' #這個文件表示”哪些程度的癥狀“會導(dǎo)致“乳腺癌的不同發(fā)展期”的數(shù)據(jù)集,同時也包含無關(guān)癥狀
data = pd.read_csv(inputfile, header=None, dtype = object)
start = time.clock() #計時開始
print(u'\n轉(zhuǎn)換原始數(shù)據(jù)至0-1矩陣...')
ct = lambda x : pd.Series(1, index = x) #轉(zhuǎn)換0-1矩陣的過渡函數(shù)
b = map(ct, data.as_matrix()) #用map方式執(zhí)行
print("b=",b)
data = pd.DataFrame(b)#轉(zhuǎn)化成數(shù)據(jù)框的時候,一些沒有的癥狀就會被加進來
data=data.fillna(0) #實現(xiàn)矩陣轉(zhuǎn)換,空值用0填充
print("data=",data)
end = time.clock() #計時結(jié)束
print(u'\n轉(zhuǎn)換完畢,用時:%0.2f秒' %(end-start))
del b #刪除中間變量b,節(jié)省內(nèi)存
#以上的工作是把各種癥狀的組合轉(zhuǎn)化成矢量
#
support = 0.06 #最小支持度
confidence = 0.87 #最小置信度
ms = '---' #連接符,默認(rèn)'--',用來區(qū)分不同元素,如A--B。需要保證原始表格中不含有該字符
start = time.clock() #計時開始
print(u'\n開始搜索關(guān)聯(lián)規(guī)則...')
find_rule(data, support, confidence, ms)
end = time.clock() #計時結(jié)束
print(u'\n搜索完成,用時:%0.2f秒' %(end-start))
☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆第2部分代碼結(jié)束☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆
輸出結(jié)果(也就是所得挖掘結(jié)果):
? support confidence
A3---F4---H4 0.078495 0.879518
C3---F4---H4 0.075269 0.875000
順便解釋下基本概念:
support指的是,或關(guān)系
Support(A=>B)=P(AUB)
置信度值得是:條件概率
Confidence(A=>B)=P(B|A)
那么以上第一行的結(jié)果可以解釋為:當(dāng)肝氣郁結(jié)癥型系數(shù)位于A3區(qū)間,并且 肝腎陰虛癥型系數(shù)位于F4區(qū)間,在這兩個前提的條件下,處于乳腺癌H4階段的概率為0.879518
在總樣本中,這種情況發(fā)生的概率是0.078495
總結(jié)
以上是生活随笔為你收集整理的《python数据分析与挖掘实战》第八章详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 主播探秘 AMD 实验室,发现 AM5
- 下一篇: 浏览器如何清理历史记录