matplotlib 是python最著名的繪圖庫,它提供了一整套和matlab相似的命令API,十分適合交互式地進行制圖。而且也可以方便地將它作為繪圖控件,嵌入GUI應用程序中。
它的文檔相當完備,并且 Gallery頁面 中有上百幅縮略圖,打開之后都有源程序。因此如果你需要繪制某種類型的圖,只需要在這個頁面中瀏覽/復制/粘貼一下,基本上都能搞定。
本章節(jié)作為matplotlib的入門介紹,將較為深入地挖掘幾個例子,從中理解和學習matplotlib繪圖的一些基本概念。
matplotlib的pyplot子庫提供了和matlab類似的繪圖API,方便用戶快速繪制2D圖表。讓我們先來看一個簡單的例子:
# -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltx = np.linspace(0, 10, 1000)y = np.sin(x)z = np.cos(x**2)plt.figure(figsize=(8,4))plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)plt.plot(x,z,"b--",label="$cos(x^2)$")plt.xlabel("Time(s)")plt.ylabel("Volt")plt.title("PyPlot First Example")plt.ylim(-1.2,1.2)plt.legend()plt.show()
圖5.1 調(diào)用pyplot庫快速將數(shù)據(jù)繪制成曲線圖
matplotlib中的快速繪圖的函數(shù)庫可以通過如下語句載入:
import matplotlib.pyplot as plt
pylab模塊
matplotlib還提供了名為pylab的模塊,其中包括了許多numpy和pyplot中常用的函數(shù),方便用戶快速進行計算和繪圖,可以用于IPython中的快速交互式使用。
接下來調(diào)用figure創(chuàng)建一個繪圖對象,并且使它成為當前的繪圖對象。
plt.figure(figsize=(8,4))
也可以不創(chuàng)建繪圖對象直接調(diào)用接下來的plot函數(shù)直接繪圖,matplotlib會為我們自動創(chuàng)建一個繪圖對象。如果需要同時繪制多幅圖表的話,可以是給figure傳遞一個整數(shù)參數(shù)指定圖標的序號,如果所指定序號的繪圖對象已經(jīng)存在的話,將不創(chuàng)建新的對象,而只是讓它成為當前繪圖對象。
通過figsize參數(shù)可以指定繪圖對象的寬度和高度,單位為英寸;dpi參數(shù)指定繪圖對象的分辨率,即每英寸多少個像素,缺省值為80。因此本例中所創(chuàng)建的圖表窗口的寬度為8*80 = 640像素。
但是用工具欄中的保存按鈕保存下來的png圖像的大小是800*400像素。這是因為保存圖表用的函數(shù)savefig使用不同的DPI配置,savefig函數(shù)也有一個dpi參數(shù),如果不設置的話,將使用matplotlib配置文件中的配置,此配置可以通過如下語句進行查看,關于配置文件將在后面的章節(jié)進行介紹:
>>> import matplotlib>>> matplotlib.rcParams["savefig.dpi"]100
下面的兩行程序通過調(diào)用plot函數(shù)在當前的繪圖對象中進行繪圖:
plt.plot(x,y,label="$sin(x)$",color="red",linewidth=2)plt.plot(x,z,"b--",label="$cos(x^2)$")
plot函數(shù)的調(diào)用方式很靈活,第一句將x,y數(shù)組傳遞給plot之后,用關鍵字參數(shù)指定各種屬性:
第二句直接通過第三個參數(shù)"b--"指定曲線的顏色和線型,這個參數(shù)稱為格式化參數(shù),它能夠通過一些易記的符號快速指定曲線的樣式。其中b表示藍色,"--"表示線型為虛線。在IPython中輸入 "plt.plot?" 可以查看格式化字符串的詳細配置。
接下來通過一系列函數(shù)設置繪圖對象的各個屬性:
plt.xlabel("Time(s)")plt.ylabel("Volt")plt.title("PyPlot First Example")plt.ylim(-1.2,1.2)plt.legend()
最后調(diào)用plt.show()顯示出我們創(chuàng)建的所有繪圖對象。
matplotlib所繪制的圖的每個組成部分都對應有一個對象,我們可以通過調(diào)用這些對象的屬性設置方法set_*或者pyplot的屬性設置函數(shù)setp設置其屬性值。例如plot函數(shù)返回一個 matplotlib.lines.Line2D 對象的列表,下面的例子顯示如何設置Line2D對象的屬性:
>>> import numpy as np>>> import matplotlib.pyplot as plt>>> x = np.arange(0, 5, 0.1)>>> line, = plt.plot(x, x*x) # plot返回一個列表,通過line,獲取其第一個元素>>> # 調(diào)用Line2D對象的set_*方法設置屬性值>>> line.set_antialiased(False)
>>> # 同時繪制sin和cos兩條曲線,lines是一個有兩個Line2D對象的列表>>> lines = plt.plot(x, np.sin(x), x, np.cos(x)) #>>> # 調(diào)用setp函數(shù)同時配置多個Line2D對象的多個屬性值>>> plt.setp(lines, color="r", linewidth=2.0)
這段例子中,通過調(diào)用Line2D對象line的set_antialiased方法,關閉對象的反鋸齒效果?;蛘咄ㄟ^調(diào)用plt.setp函數(shù)配置多個Line2D對象的顏色和線寬屬性。
同樣我們可以通過調(diào)用Line2D對象的get_*方法,或者plt.getp函數(shù)獲取對象的屬性值:
>>> line.get_linewidth()1.0>>> plt.getp(lines[0], "color") # 返回color屬性'r'>>> plt.getp(lines[1]) # 輸出全部屬性alpha = 1.0animated = Falseantialiased or aa = Trueaxes = Axes(0.125,0.1;0.775x0.8)... ...
注意getp函數(shù)只能對一個對象進行操作,它有兩種用法:
matplotlib的整個圖表為一個Figure對象,此對象在調(diào)用plt.figure函數(shù)時返回,我們也可以通過plt.gcf函數(shù)獲取當前的繪圖對象:
>>> f = plt.gcf()>>> plt.getp(f)alpha = 1.0animated = False...
Figure對象有一個axes屬性,其值為AxesSubplot對象的列表,每個AxesSubplot對象代表圖表中的一個子圖,前面所繪制的圖表只包含一個子圖,當前子圖也可以通過plt.gca獲得:
>>> plt.getp(f, "axes")[<matplotlib.axes.AxesSubplot object at 0x05CDD170>]>>> plt.gca()<matplotlib.axes.AxesSubplot object at 0x05CDD170>
用plt.getp可以發(fā)現(xiàn)AxesSubplot對象有很多屬性,例如它的lines屬性為此子圖所包括的 Line2D 對象列表:
>>> alllines = plt.getp(plt.gca(), "lines")>>> alllines<a list of 3 Line2D objects>>>> alllines[0] == line # 其中的第一條曲線就是最開始繪制的那條曲線True
通過這種方法我們可以很容易地查看對象的屬性和它們之間的包含關系,找到需要配置的屬性。
一個繪圖對象(figure)可以包含多個軸(axis),在Matplotlib中用軸表示一個繪圖區(qū)域,可以將其理解為子圖。上面的第一個例子中,繪圖對象只包括一個軸,因此只顯示了一個軸(子圖)。我們可以使用subplot函數(shù)快速繪制有多個軸的圖表。subplot函數(shù)的調(diào)用形式如下:
subplot(numRows, numCols, plotNum)
subplot將整個繪圖區(qū)域等分為numRows行 * numCols列個子區(qū)域,然后按照從左到右,從上到下的順序?qū)γ總€子區(qū)域進行編號,左上的子區(qū)域的編號為1。如果numRows,numCols和plotNum這三個數(shù)都小于10的話,可以把它們縮寫為一個整數(shù),例如subplot(323)和subplot(3,2,3)是相同的。subplot在plotNum指定的區(qū)域中創(chuàng)建一個軸對象。如果新創(chuàng)建的軸和之前創(chuàng)建的軸重疊的話,之前的軸將被刪除。
下面的程序創(chuàng)建3行2列共6個軸,通過axisbg參數(shù)給每個軸設置不同的背景顏色。
for idx, color in enumerate("rgbyck"): plt.subplot(320+idx+1, axisbg=color)plt.show()
圖5.2 用subplot函數(shù)將Figure分為六個子圖區(qū)域
如果希望某個軸占據(jù)整個行或者列的話,可以如下調(diào)用subplot:
plt.subplot(221) # 第一行的左圖plt.subplot(222) # 第一行的右圖plt.subplot(212) # 第二整行plt.show()
圖5.3 將Figure分為三個子圖區(qū)域
當繪圖對象中有多個軸的時候,可以通過工具欄中的Configure Subplots按鈕,交互式地調(diào)節(jié)軸之間的間距和軸與邊框之間的距離。如果希望在程序中調(diào)節(jié)的話,可以調(diào)用subplots_adjust函數(shù),它有l(wèi)eft, right, bottom, top, wspace, hspace等幾個關鍵字參數(shù),這些參數(shù)的值都是0到1之間的小數(shù),它們是以繪圖區(qū)域的寬高為1進行正規(guī)化之后的坐標或者長度。
一幅圖有許多需要配置的屬性,例如顏色、字體、線型等等。我們在繪圖時,并沒有一一對這些屬性進行配置,許多都直接采用了Matplotlib的缺省配置。Matplotlib將缺省配置保存在一個文件中,通過更改這個文件,我們可以修改這些屬性的缺省值。
Matplotlib 使用配置文件 matplotlibrc 時的搜索順序如下:
通過下面的語句可以獲取用戶配置路徑:
>>> import matplotlib>>> matplotlib.get_configdir()'C:\\Documents and Settings\\zhang\\.matplotlib'
通過下面的語句可以獲得目前使用的配置文件的路徑:
>>> import matplotlib>>> matplotlib.matplotlib_fname()'C:\\Python26\\lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc'
由于在當前路徑和用戶配置路徑中都沒有找到位置文件,因此最后使用的是系統(tǒng)配置路徑下的配置文件。如果你將matplotlibrc復制一份到腳本的當前目錄下:
>>> import os>>> os.getcwd()'C:\\zhang\\doc'
復制配置文件之后再運行:
>>> matplotlib.matplotlib_fname()'C:\\zhang\\doc\\matplotlibrc'
如果你用文本編輯器打開此配置文件的話,你會發(fā)現(xiàn)它實際上是定義了一個字典。為了對眾多的配置進行區(qū)分,關鍵字可以用點分開。
配置文件的讀入可以使用 rc_params 函數(shù),它返回一個配置字典:
>>> matplotlib.rc_params(){'agg.path.chunksize': 0, 'axes.axisbelow': False, 'axes.edgecolor': 'k', 'axes.facecolor': 'w', ... ...
在matplotlib模塊載入的時候會調(diào)用rc_params,并把得到的配置字典保存到rcParams變量中:
>>> matplotlib.rcParams{'agg.path.chunksize': 0,'axes.axisbelow': False,... ...
matplotlib將使用rcParams中的配置進行繪圖。用戶可以直接修改此字典中的配置,所做的改變會反映到此后所繪制的圖中。例如下面的腳本所繪制的線將帶有圓形的點標識符:
>>> matplotlib.rcParams["lines.marker"] = "o">>> import pylab>>> pylab.plot([1,2,3])>>> pylab.show()
為了方便配置,可以使用rc函數(shù),下面的例子同時配置點標識符、線寬和顏色:
>>> matplotlib.rc("lines", marker="x", linewidth=2, color="red")
如果希望恢復到缺省的配置(matplotlib載入時從配置文件讀入的配置)的話,可以調(diào)用 rcdefaults 函數(shù)。
>>> matplotlib.rcdefaults()
如果手工修改了配置文件,希望重新從配置文件載入最新的配置的話,可以調(diào)用:
>>> matplotlib.rcParams.update( matplotlib.rc_params() )
matplotlib API包含有三層:
FigureCanvas和Renderer需要處理底層的繪圖操作,例如使用wxPython在界面上繪圖,或者使用PostScript繪制PDF。Artist則處理所有的高層結構,例如處理圖表、文字和曲線等的繪制和布局。通常我們只和Artist打交道,而不需要關心底層的繪制細節(jié)。
Artists分為簡單類型和容器類型兩種。簡單類型的Artists為標準的繪圖元件,例如Line2D、 Rectangle、 Text、AxesImage 等等。而容器類型則可以包含許多簡單類型的Artists,使它們組織成一個整體,例如Axis、 Axes、Figure等。
直接使用Artists創(chuàng)建圖表的標準流程如下:
下面首先調(diào)用pyplot.figure輔助函數(shù)創(chuàng)建Figure對象,然后調(diào)用Figure對象的add_axes方法在其中創(chuàng)建一個Axes對象,add_axes的參數(shù)是一個形如[left, bottom, width, height]的列表,這些數(shù)值分別指定所創(chuàng)建的Axes對象相對于fig的位置和大小,取值范圍都在0到1之間:
>>> import matplotlib.pyplot as plt>>> fig = plt.figure()>>> ax = fig.add_axes([0.15, 0.1, 0.7, 0.3])
然后我們調(diào)用ax的plot方法繪圖,創(chuàng)建一條曲線,并且返回此曲線對象(Line2D)。
>>> line, = ax.plot([1,2,3],[1,2,1])>>> ax.lines[<matplotlib.lines.Line2D object at 0x0637A3D0>]>>> line<matplotlib.lines.Line2D object at 0x0637A3D0>
ax.lines是一個為包含ax的所有曲線的列表,后續(xù)的ax.plot調(diào)用會往此列表中添加新的曲線。如果想刪除某條曲線的話,直接從此列表中刪除即可。
Axes對象還包括許多其它的Artists對象,例如我們可以通過調(diào)用set_xlabel設置其X軸上的標題:
>>> ax.set_xlabel("time")
如果我們查看set_xlabel的源代碼的話,會發(fā)現(xiàn)它是通過調(diào)用下面的語句實現(xiàn)的:
self.xaxis.set_label_text(xlabel)
如果我們一直跟蹤下去,會發(fā)現(xiàn)Axes的xaxis屬性是一個XAxis對象:
>>> ax.xaxis<matplotlib.axis.XAxis object at 0x06343230>
XAxis的label屬性是一個Text對象:
>>> ax.xaxis.label<matplotlib.text.Text object at 0x06343290>
而Text對象的_text屬性為我們設置的值:
>>> ax.xaxis.label._text'time'
這些對象都是Artists,因此也可以調(diào)用它們的屬性獲取函數(shù)來獲得相應的屬性:
>>> ax.xaxis.label.get_text()'time'
圖表中的每個元素都用一個matplotlib的Artist對象表示,而每個Artist對象都有一大堆屬性控制其顯示效果。例如Figure對象和Axes對象都有patch屬性作為其背景,它的值是一個Rectangle對象。通過設置此它的一些屬性可以修改Figrue圖表的背景顏色或者透明度等屬性,下面的例子將圖表的背景顏色設置為綠色:
>>> fig = plt.figure()>>> fig.show()>>> fig.patch.set_color("g")>>> fig.canvas.draw()
patch的color屬性通過set_color函數(shù)進行設置,屬性修改之后并不會立即反映到圖表的顯示上,還需要調(diào)用fig.canvas.draw()函數(shù)才能夠更新顯示。
下面是Artist對象都具有的一些屬性:
Artist對象的所有屬性都通過相應的 get_* 和 set_* 函數(shù)進行讀寫,例如下面的語句將alpha屬性設置為當前值的一半:
>>> fig.set_alpha(0.5*fig.get_alpha())
如果你想用一條語句設置多個屬性的話,可以使用set函數(shù):
>>> fig.set(alpha=0.5, zorder=2)
使用前面介紹的 matplotlib.pyplot.getp 函數(shù)可以方便地輸出Artist對象的所有屬性名和值。
>>> plt.getp(fig.patch) aa = True alpha = 1.0 animated = False antialiased or aa = True ... ...
現(xiàn)在我們知道如何觀察和修改已知的某個Artist對象的屬性,接下來要解決如何找到指定的Artist對象。前面我們介紹過Artist對象有容器類型和簡單類型兩種,這一節(jié)讓我們來詳細看看容器類型的內(nèi)容。
最大的Artist容器是matplotlib.figure.Figure,它包括組成圖表的所有元素。圖表的背景是一個Rectangle對象,用Figure.patch屬性表示。當你通過調(diào)用add_subplot或者add_axes方法往圖表中添加軸(子圖時),這些子圖都將添加到Figure.axes屬性中,同時這兩個方法也返回添加進axes屬性的對象,注意返回值的類型有所不同,實際上AxesSubplot是Axes的子類。
>>> fig = plt.figure()>>> ax1 = fig.add_subplot(211)>>> ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.3])>>> ax1<matplotlib.axes.AxesSubplot object at 0x056BCA90>>>> ax2<matplotlib.axes.Axes object at 0x056BC910>>>> fig.axes[<matplotlib.axes.AxesSubplot object at 0x056BCA90>,<matplotlib.axes.Axes object at 0x056BC910>]
為了支持pylab中的gca()等函數(shù),F(xiàn)igure對象內(nèi)部保存有當前軸的信息,因此不建議直接對Figure.axes屬性進行列表操作,而應該使用add_subplot, add_axes, delaxes等方法進行添加和刪除操作。但是使用for循環(huán)對axes中的每個元素進行操作是沒有問題的,下面的語句打開所有子圖的柵格。
>>> for ax in fig.axes: ax.grid(True)
Figure對象可以擁有自己的文字、線條以及圖像等簡單類型的Artist。缺省的坐標系統(tǒng)為像素點,但是可以通過設置Artist對象的transform屬性修改坐標系的轉換方式。最常用的Figure對象的坐標系是以左下角為坐標原點(0,0),右上角為坐標(1,1)。下面的程序創(chuàng)建并添加兩條直線到fig中:
>>> from matplotlib.lines import Line2D>>> fig = plt.figure()>>> line1 = Line2D([0,1],[0,1], transform=fig.transFigure, figure=fig, color="r")>>> line2 = Line2D([0,1],[1,0], transform=fig.transFigure, figure=fig, color="g")>>> fig.lines.extend([line1, line2])>>> fig.show()
圖5.4 在Figure對象中手工繪制直線
注意為了讓所創(chuàng)建的Line2D對象使用fig的坐標,我們將fig.TransFigure賦給Line2D對象的transform屬性;為了讓Line2D對象知道它是在fig對象中,我們還設置其figure屬性為fig;最后還需要將創(chuàng)建的兩個Line2D對象添加到fig.lines屬性中去。
Figure對象有如下屬性包含其它的Artist對象:
Axes容器是整個matplotlib庫的核心,它包含了組成圖表的眾多Artist對象,并且有許多方法函數(shù)幫助我們創(chuàng)建、修改這些對象。和Figure一樣,它有一個patch屬性作為背景,當它是笛卡爾坐標時,patch屬性是一個Rectangle對象,而當它是極坐標時,patch屬性則是Circle對象。例如下面的語句設置Axes對象的背景顏色為綠色:
>>> fig = plt.figure()>>> ax = fig.add_subplot(111)>>> ax.patch.set_facecolor("green")
當你調(diào)用Axes的繪圖方法(例如plot),它將創(chuàng)建一組Line2D對象,并將所有的關鍵字參數(shù)傳遞給這些Line2D對象,并將它們添加進Axes.lines屬性中,最后返回所創(chuàng)建的Line2D對象列表:
>>> x, y = np.random.rand(2, 100)>>> line, = ax.plot(x, y, "-", color="blue", linewidth=2)>>> line<matplotlib.lines.Line2D object at 0x03007030>>>> ax.lines[<matplotlib.lines.Line2D object at 0x03007030>]
注意plot返回的是一個Line2D對象的列表,因為我們可以傳遞多組X,Y軸的數(shù)據(jù),一次繪制多條曲線。
與plot方法類似,繪制直方圖的方法bar和繪制柱狀統(tǒng)計圖的方法hist將創(chuàng)建一個Patch對象的列表,每個元素實際上都是Patch的子類Rectangle,并且將所創(chuàng)建的Patch對象都添加進Axes.patches屬性中:
>>> ax = fig.add_subplot(111)>>> n, bins, rects = ax.hist(np.random.randn(1000), 50, facecolor="blue")>>> rects<a list of 50 Patch objects>>>> rects[0]<matplotlib.patches.Rectangle object at 0x05BC2350>>>> ax.patches[0]<matplotlib.patches.Rectangle object at 0x05BC2350>
一般我們不會直接對Axes.lines或者Axes.patches屬性進行操作,而是調(diào)用add_line或者add_patch等方法,這些方法幫助我們完成許多屬性設置工作:
>>> fig = plt.figure()>>> ax = fig.add_subplot(111)>>> rect = matplotlib.patches.Rectangle((1,1), width=5, height=12)>>> print rect.get_axes() # rect的axes屬性為空None>>> rect.get_transform() # rect的transform屬性為缺省值BboxTransformTo(Bbox(array([[ 1., 1.], [ 6., 13.]])))>>> ax.add_patch(rect) # 將rect添加進ax<matplotlib.patches.Rectangle object at 0x05C34E50>>>> rect.get_axes() # 于是rect的axes屬性就是ax<matplotlib.axes.AxesSubplot object at 0x05C09CB0>>>> # rect的transform屬性和ax的transData相同>>> rect.get_transform()... # 太長,省略>>> ax.transData... # 太長,省略>>> ax.get_xlim() # ax的X軸范圍為0到1,無法顯示完整的rect(0.0, 1.0)>>> ax.dataLim._get_bounds() # 數(shù)據(jù)的范圍和rect的大小一致(1.0, 1.0, 5.0, 12.0)>>> ax.autoscale_view() # 自動調(diào)整坐標軸范圍>>> ax.get_xlim() # 于是X軸可以完整顯示rect(1.0, 6.0)>>> plt.show()
通過上面的例子我們可以看出,add_patch方法幫助我們設置了rect的axes和transform屬性。
下面詳細列出Axes包含各種Artist對象的屬性:
下面列出Axes的創(chuàng)建Artist對象的方法:
Axes的方法 | 所創(chuàng)建的對象 | 添加進的列表 |
annotate | Annotate | texts |
bars | Rectangle | patches |
errorbar | Line2D, Rectangle | lines,patches |
fill | Polygon | patches |
hist | Rectangle | patches |
imshow | AxesImage | images |
legend | Legend | legends |
plot | Line2D | lines |
scatter | PolygonCollection | Collections |
text | Text | texts |
下面以繪制散列圖(scatter)為例,驗證一下:
>>> fig = plt.figure()>>> ax = fig.add_subplot(111)>>> t = ax.scatter(np.random.rand(20), np.random.rand(20))>>> t # 返回值為CircleCollection對象<matplotlib.collections.CircleCollection object at 0x06004230>>>> ax.collections # 返回的對象已經(jīng)添加進了collections列表中[<matplotlib.collections.CircleCollection object at 0x06004230>]>>> fig.show()>>> t.get_sizes() # 獲得Collection的點數(shù)20
圖5.5 用scatter函數(shù)繪制散列圖
Axis容器包括坐標軸上的刻度線、刻度文本、坐標網(wǎng)格以及坐標軸標題等內(nèi)容??潭劝ㄖ骺潭群透笨潭?,分別通過Axis.get_major_ticks和Axis.get_minor_ticks方法獲得。每個刻度線都是一個XTick或者YTick對象,它包括實際的刻度線和刻度文本。為了方便訪問刻度線和文本,Axis對象提供了get_ticklabels和get_ticklines方法分別直接獲得刻度線和刻度文本:
>>> pl.plot([1,2,3],[4,5,6])[<matplotlib.lines.Line2D object at 0x0AD3B670>]>>> pl.show()>>> axis = pl.gca().xaxis>>> axis.get_ticklocs() # 獲得刻度的位置列表array([ 1. , 1.5, 2. , 2.5, 3. ])>>> axis.get_ticklabels() # 獲得刻度標簽列表<a list of 5 Text major ticklabel objects>>>> [x.get_text() for x in axis.get_ticklabels()] # 獲得刻度的文本字符串[u'1.0', u'1.5', u'2.0', u'2.5', u'3.0']>>> axis.get_ticklines() # 獲得主刻度線列表,圖的上下刻度線共10條<a list of 10 Line2D ticklines objects>>>> axis.get_ticklines(minor=True) # 獲得副刻度線列表<a list of 0 Line2D ticklines objects>
獲得刻度線或者刻度標簽之后,可以設置其各種屬性,下面設置刻度線為綠色粗線,文本為紅色并且旋轉45度:
>>> for label in axis.get_ticklabels():... label.set_color("red")... label.set_rotation(45)... label.set_fontsize(16)...>>> for line in axis.get_ticklines():... line.set_color("green")... line.set_markersize(25)... line.set_markeredgewidth(3)
最終的結果圖如下:
圖5.6 手工配置X軸的刻度線和刻度文本的樣式
上面的例子中,獲得的副刻度線列表為空,這是因為用于計算副刻度的對象缺省為NullLocator,它不產(chǎn)生任何刻度線;而計算主刻度的對象為AutoLocator,它會根據(jù)當前的縮放等配置自動計算刻度的位置:
>>> axis.get_minor_locator() # 計算副刻度的對象<matplotlib.ticker.NullLocator instance at 0x0A014300>>>> axis.get_major_locator() # 計算主刻度的對象<matplotlib.ticker.AutoLocator instance at 0x09281B20>
我們可以使用程序為Axis對象設置不同的Locator對象,用來手工設置刻度的位置;設置Formatter對象用來控制刻度文本的顯示。下面的程序設置X軸的主刻度為pi/4,副刻度為pi/20,并且主刻度上的文本以pi為單位:
# -*- coding: utf-8 -*-import matplotlib.pyplot as plfrom matplotlib.ticker import MultipleLocator, FuncFormatterimport numpy as npx = np.arange(0, 4*np.pi, 0.01)y = np.sin(x)pl.figure(figsize=(8,4))pl.plot(x, y)ax = pl.gca()def pi_formatter(x, pos): """ 比較羅嗦地將數(shù)值轉換為以pi/4為單位的刻度文本 """ m = np.round(x / (np.pi/4)) n = 4 if m%2==0: m, n = m/2, n/2 if m%2==0: m, n = m/2, n/2 if m == 0: return "0" if m == 1 and n == 1: return "$\pi$" if n == 1: return r"$%d \pi$" % m if m == 1: return r"$\frac{\pi}{%d}$" % n return r"$\frac{%d \pi}{%d}$" % (m,n)# 設置兩個坐標軸的范圍pl.ylim(-1.5,1.5)pl.xlim(0, np.max(x))# 設置圖的底邊距pl.subplots_adjust(bottom = 0.15)pl.grid() #開啟網(wǎng)格# 主刻度為pi/4ax.xaxis.set_major_locator( MultipleLocator(np.pi/4) )# 主刻度文本用pi_formatter函數(shù)計算ax.xaxis.set_major_formatter( FuncFormatter( pi_formatter ) )# 副刻度為pi/20ax.xaxis.set_minor_locator( MultipleLocator(np.pi/20) )# 設置刻度文本的大小for tick in ax.xaxis.get_major_ticks(): tick.label1.set_fontsize(16)pl.show()
關于刻度的定位和文本格式的東西都在matplotlib.ticker中定義,程序中使用到如下兩個類:
此外還有很多預定義的Locator和Formatter類,詳細內(nèi)容請參考相應的API文檔。
圖5.7 手工配置X軸的刻度線的位置和文本,并開啟副刻度