上篇中,實現了創建決策樹但并不直觀,這里學習繪制決策樹,便于直觀理解。
Matplotlib提供了名為pylab的模塊,其中包括了許多numpy和pyplot中常用的函數,方便用戶快速進行計算和繪圖,
可以用于IPython中的快速交互式使用。
Matplotlib中的快速繪圖的函數庫可以通過如下語句載入:
[python] view plain
copy print?
import?matplotlib.pyplot?as?plt??
import matplotlib.pyplot as plt繪制樹形圖,我們需要定義樹和葉的形態,還必須要知道有多少個葉節點和判斷節點,還有樹的層數,這樣才能確定樹的大小,繪制繪圖區
首先注解繪制的樹節點和葉節點以及箭頭
[python] view plain
copy print?
??decisionNode?=?dict(boxstyle=”sawtooth”,?fc=“0.8”)???leafNode?=?dict(boxstyle=”round4”,?fc=“0.8”)???arrow_args?=?dict(arrowstyle=”<-“)???????????def?plotNode(nodeTxt,?centerPt,?parentPt,?nodeType):??????createPlot.ax1.annotate(nodeTxt,?xy=parentPt,??xycoords=’axes?fraction’,???????????????xytext=centerPt,?textcoords=’axes?fraction’,???????????????va=”center”,?ha=“center”,?bbox=nodeType,?arrowprops=arrow_args?)??
#定義文本框和箭頭格式
decisionNode = dict(boxstyle=”sawtooth”, fc=”0.8”) #定義判斷節點形態
leafNode = dict(boxstyle=”round4”, fc=”0.8”) #定義葉節點形態
arrow_args = dict(arrowstyle=”<-“) #定義箭頭
#繪制帶箭頭的注解 #nodeTxt:節點的文字標注, centerPt:節點中心位置, #parentPt:箭頭起點位置(上一節點位置), nodeType:節點屬性 def plotNode(nodeTxt, centerPt, parentPt, nodeType): createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', xytext=centerPt, textcoords='axes fraction', va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )
然后得到葉節點的數目和樹的層數
[python] view plain
copy print?
??def?getNumLeafs(myTree):??????numLeafs?=?0??????firstStr?=?myTree.keys()[0]???????secondDict?=?myTree[firstStr]???????for?key?in?secondDict.keys():??????????if?type(secondDict[key]).__name__==‘dict’:??????????????numLeafs?+=?getNumLeafs(secondDict[key])???????????else:???numLeafs?+=1???????return?numLeafs??????def?getTreeDepth(myTree):??????maxDepth?=?0??????firstStr?=?myTree.keys()[0]??????secondDict?=?myTree[firstStr]??????for?key?in?secondDict.keys():??????????if?type(secondDict[key]).__name__==‘dict’:??????????????thisDepth?=?1?+?getTreeDepth(secondDict[key])???????????else:???thisDepth?=?1????????????????????if?thisDepth?>?maxDepth:??????????????maxDepth?=?thisDepth??????return?maxDepth??
#計算葉節點數
def getNumLeafs(myTree):numLeafs = 0firstStr = myTree.keys()[0] secondDict = myTree[firstStr] for key in secondDict.keys():if type(secondDict[key]).__name__=='dict':#是否是字典numLeafs += getNumLeafs(secondDict[key]) #遞歸調用getNumLeafselse: numLeafs +=1 #如果是葉節點,則葉節點+1return numLeafs #計算數的層數 def getTreeDepth(myTree): maxDepth = 0 firstStr = myTree.keys()[0] secondDict = myTree[firstStr] for key in secondDict.keys(): if type(secondDict[key]).__name__=='dict':#是否是字典 thisDepth = 1 + getTreeDepth(secondDict[key]) #如果是字典,則層數加1,再遞歸調用getTreeDepth else: thisDepth = 1 #得到最大層數 if thisDepth > maxDepth: maxDepth = thisDepth return maxDepth有了注解和計算樹形圖的位置的參數,就可以繪制樹形圖了
為了清晰簡明,在父子節點之間加入文本標簽信息
[python] view plain
copy print?
????def?plotMidText(cntrPt,?parentPt,?txtString):??????xMid?=?(parentPt[0]-cntrPt[0])/2.0?+?cntrPt[0]??????yMid?=?(parentPt[1]-cntrPt[1])/2.0?+?cntrPt[1]??????createPlot.ax1.text(xMid,?yMid,?txtString,?va=”center”,?ha=“center”,?rotation=30)??
#在父子節點間填充文本信息 #cntrPt:子節點位置, parentPt:父節點位置, txtString:標注內容 def plotMidText(cntrPt, parentPt, txtString): xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0] yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1] createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)然后繪制樹形圖;
[python] view plain
copy print?
????def?plotTree(myTree,?parentPt,?nodeTxt):??????numLeafs?=?getNumLeafs(myTree)????????depth?=?getTreeDepth(myTree)??????????firstStr?=?myTree.keys()[0]?????????????????cntrPt?=?(plotTree.xOff?+?(1.0?+?float(numLeafs))/2.0/plotTree.totalW,?plotTree.yOff)??????plotMidText(cntrPt,?parentPt,?nodeTxt)???????plotNode(firstStr,?cntrPt,?parentPt,?decisionNode)???????secondDict?=?myTree[firstStr]??????plotTree.yOff?=?plotTree.yOff?-?1.0/plotTree.totalD??????for?key?in?secondDict.keys():??????????if?type(secondDict[key]).__name__==‘dict’:??????????????plotTree(secondDict[key],cntrPt,str(key))??????????????????else:?????????????????plotTree.xOff?=?plotTree.xOff?+?1.0/plotTree.totalW??????????????plotNode(secondDict[key],?(plotTree.xOff,?plotTree.yOff),?cntrPt,?leafNode)??????????????plotMidText((plotTree.xOff,?plotTree.yOff),?cntrPt,?str(key))??????plotTree.yOff?=?plotTree.yOff?+?1.0/plotTree.totalD??????def?createPlot(inTree):??????fig?=?plt.figure(1,?facecolor=‘white’)??????fig.clf()??????axprops?=?dict(xticks=[],?yticks=[])??????createPlot.ax1?=?plt.subplot(111,?frameon=False,?**axprops)??????????plotTree.totalW?=?float(getNumLeafs(inTree))???????plotTree.totalD?=?float(getTreeDepth(inTree))???????plotTree.xOff?=?-0.5/plotTree.totalW;?plotTree.yOff?=?1.0;??????plotTree(inTree,?(0.5,1.0),?”)??????plt.show()??
#繪制樹形圖 #myTree:樹的字典, parentPt:父節點, nodeTxt:節點的文字標注 def plotTree(myTree, parentPt, nodeTxt): numLeafs = getNumLeafs(myTree) #樹葉節點數 depth = getTreeDepth(myTree) #樹的層數 firstStr = myTree.keys()[0] #節點標簽 #計算當前節點的位置 cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff) plotMidText(cntrPt, parentPt, nodeTxt) #在父子節點間填充文本信息 plotNode(firstStr, cntrPt, parentPt, decisionNode) #繪制帶箭頭的注解 secondDict = myTree[firstStr] plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD for key in secondDict.keys(): if type(secondDict[key]).__name__=='dict':#判斷是不是字典, plotTree(secondDict[key],cntrPt,str(key)) #遞歸繪制樹形圖 else: #如果是葉節點 plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode) plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key)) plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD #創建繪圖區 def createPlot(inTree): fig = plt.figure(1, facecolor='white') fig.clf() axprops = dict(xticks=[], yticks=[]) createPlot.ax1 = plt.subplot(111, frameon=False, **axprops) plotTree.totalW = float(getNumLeafs(inTree)) #樹的寬度 plotTree.totalD = float(getTreeDepth(inTree)) #樹的深度 plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0; plotTree(inTree, (0.5,1.0), '') plt.show()其中createPlot()是主函數,創建繪圖區,計算樹形圖的尺寸大小,它調用plotTree()等函數,plotTree()遞歸畫出整個樹形圖。
加載之前創建了tree模塊和這個treeplot模塊,在命令提示符下輸入
[python] view plain
copy print?
>>>?import?treeplot??>>>?import?tree??>>>?myDat,labels?=?tree.createDataSet()??>>>?myTree?=?tree.createTree(myDat,labels)??>>>?treeplot.createPlot(myTree)??
>>> import treeplot
>>> import tree
>>> myDat,labels = tree.createDataSet()
>>> myTree = tree.createTree(myDat,labels)
>>> treeplot.createPlot(myTree)得到正確的樹形圖
用創建的tree模塊和treeplot模塊,使用決策樹預測隱形眼鏡類型;
在命令提示符下輸入
[python] view plain
copy print?
>>>?import?tree??>>>?import?treeplot??>>>?fr?=?open(’lenses.txt’)??>>>?lenses?=?[inst.strip().split(’\t’)?for?inst?in?fr.readlines()]??>>>?lensesLabels?=?[’age’,‘prescript’,‘astigmatic’,‘tearRate’]??>>>?lensesTree?=?tree.createTree(lenses,lensesLabels)??>>>?treeplot.createPlot(lensesTree)??
>>> import tree
>>> import treeplot
>>> fr = open('lenses.txt')
>>> lenses = [inst.strip().split('\t') for inst in fr.readlines()]
>>> lensesLabels = ['age','prescript','astigmatic','tearRate']
>>> lensesTree = tree.createTree(lenses,lensesLabels)
>>> treeplot.createPlot(lensesTree)得到如下所示
如有不足,請指出,謝謝~~
總結
以上是生活随笔為你收集整理的matPlotLib绘制决策树的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。