2020国产成人精品视频,性做久久久久久久久,亚洲国产成人久久综合一区,亚洲影院天堂中文av色

分享

matplotlib

 易小丫丫 2013-02-28

matplotlib 是python最著名的繪圖庫(kù),它提供了一整套和matlab相似的命令A(yù)PI,十分適合交互式地進(jìn)行制圖。而且也可以方便地將它作為繪圖控件,嵌入GUI應(yīng)用程序中。

它的文檔相當(dāng)完備,并且 Gallery頁(yè)面 中有上百幅縮略圖,打開(kāi)之后都有源程序。因此如果你需要繪制某種類型的圖,只需要在這個(gè)頁(yè)面中瀏覽/復(fù)制/粘貼一下,基本上都能搞定。

本章節(jié)作為matplotlib的入門(mén)介紹,將較為深入地挖掘幾個(gè)例子,從中理解和學(xué)習(xí)matplotlib繪圖的一些基本概念。

5.1 快速繪圖

matplotlib的pyplot子庫(kù)提供了和matlab類似的繪圖API,方便用戶快速繪制2D圖表。讓我們先來(lái)看一個(gè)簡(jiǎn)單的例子:

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

x = 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()
_images/pyplot_simple_plot.png

圖5.1 調(diào)用pyplot庫(kù)快速將數(shù)據(jù)繪制成曲線圖

matplotlib中的快速繪圖的函數(shù)庫(kù)可以通過(guò)如下語(yǔ)句載入:

import matplotlib.pyplot as plt

pylab模塊

matplotlib還提供了名為pylab的模塊,其中包括了許多numpy和pyplot中常用的函數(shù),方便用戶快速進(jìn)行計(jì)算和繪圖,可以用于IPython中的快速交互式使用。

接下來(lái)調(diào)用figure創(chuàng)建一個(gè)繪圖對(duì)象,并且使它成為當(dāng)前的繪圖對(duì)象。

plt.figure(figsize=(8,4))

也可以不創(chuàng)建繪圖對(duì)象直接調(diào)用接下來(lái)的plot函數(shù)直接繪圖,matplotlib會(huì)為我們自動(dòng)創(chuàng)建一個(gè)繪圖對(duì)象。如果需要同時(shí)繪制多幅圖表的話,可以是給figure傳遞一個(gè)整數(shù)參數(shù)指定圖標(biāo)的序號(hào),如果所指定序號(hào)的繪圖對(duì)象已經(jīng)存在的話,將不創(chuàng)建新的對(duì)象,而只是讓它成為當(dāng)前繪圖對(duì)象。

通過(guò)figsize參數(shù)可以指定繪圖對(duì)象的寬度和高度,單位為英寸;dpi參數(shù)指定繪圖對(duì)象的分辨率,即每英寸多少個(gè)像素,缺省值為80。因此本例中所創(chuàng)建的圖表窗口的寬度為8*80 = 640像素。

但是用工具欄中的保存按鈕保存下來(lái)的png圖像的大小是800*400像素。這是因?yàn)楸4鎴D表用的函數(shù)savefig使用不同的DPI配置,savefig函數(shù)也有一個(gè)dpi參數(shù),如果不設(shè)置的話,將使用matplotlib配置文件中的配置,此配置可以通過(guò)如下語(yǔ)句進(jìn)行查看,關(guān)于配置文件將在后面的章節(jié)進(jìn)行介紹:

>>> import matplotlib
>>> matplotlib.rcParams["savefig.dpi"]
100

下面的兩行程序通過(guò)調(diào)用plot函數(shù)在當(dāng)前的繪圖對(duì)象中進(jìn)行繪圖:

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之后,用關(guān)鍵字參數(shù)指定各種屬性:

  • label : 給所繪制的曲線一個(gè)名字,此名字在圖示(legend)中顯示。只要在字符串前后添加"$"符號(hào),matplotlib就會(huì)使用其內(nèi)嵌的latex引擎繪制的數(shù)學(xué)公式。
  • color : 指定曲線的顏色
  • linewidth : 指定曲線的寬度

第二句直接通過(guò)第三個(gè)參數(shù)"b--"指定曲線的顏色和線型,這個(gè)參數(shù)稱為格式化參數(shù),它能夠通過(guò)一些易記的符號(hào)快速指定曲線的樣式。其中b表示藍(lán)色,"--"表示線型為虛線。在IPython中輸入 "plt.plot?" 可以查看格式化字符串的詳細(xì)配置。

接下來(lái)通過(guò)一系列函數(shù)設(shè)置繪圖對(duì)象的各個(gè)屬性:

plt.xlabel("Time(s)")
plt.ylabel("Volt")
plt.title("PyPlot First Example")
plt.ylim(-1.2,1.2)
plt.legend()
  • xlabel : 設(shè)置X軸的文字
  • ylabel : 設(shè)置Y軸的文字
  • title : 設(shè)置圖表的標(biāo)題
  • ylim : 設(shè)置Y軸的范圍
  • legend : 顯示圖示

最后調(diào)用plt.show()顯示出我們創(chuàng)建的所有繪圖對(duì)象。

5.1.1 配置屬性

matplotlib所繪制的圖的每個(gè)組成部分都對(duì)應(yīng)有一個(gè)對(duì)象,我們可以通過(guò)調(diào)用這些對(duì)象的屬性設(shè)置方法set_*或者pyplot的屬性設(shè)置函數(shù)setp設(shè)置其屬性值。例如plot函數(shù)返回一個(gè) matplotlib.lines.Line2D 對(duì)象的列表,下面的例子顯示如何設(shè)置Line2D對(duì)象的屬性:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> x = np.arange(0, 5, 0.1)
>>> line, = plt.plot(x, x*x) # plot返回一個(gè)列表,通過(guò)line,獲取其第一個(gè)元素
>>> # 調(diào)用Line2D對(duì)象的set_*方法設(shè)置屬性值
>>> line.set_antialiased(False)
>>> # 同時(shí)繪制sin和cos兩條曲線,lines是一個(gè)有兩個(gè)Line2D對(duì)象的列表
>>> lines = plt.plot(x, np.sin(x), x, np.cos(x)) #
>>> # 調(diào)用setp函數(shù)同時(shí)配置多個(gè)Line2D對(duì)象的多個(gè)屬性值
>>> plt.setp(lines, color="r", linewidth=2.0)

這段例子中,通過(guò)調(diào)用Line2D對(duì)象line的set_antialiased方法,關(guān)閉對(duì)象的反鋸齒效果。或者通過(guò)調(diào)用plt.setp函數(shù)配置多個(gè)Line2D對(duì)象的顏色和線寬屬性。

同樣我們可以通過(guò)調(diào)用Line2D對(duì)象的get_*方法,或者plt.getp函數(shù)獲取對(duì)象的屬性值:

>>> line.get_linewidth()
1.0
>>> plt.getp(lines[0], "color") # 返回color屬性
'r'
>>> plt.getp(lines[1]) # 輸出全部屬性
alpha = 1.0
animated = False
antialiased or aa = True
axes = Axes(0.125,0.1;0.775x0.8)
... ...

注意getp函數(shù)只能對(duì)一個(gè)對(duì)象進(jìn)行操作,它有兩種用法:

  • 指定屬性名:返回對(duì)象的指定屬性的值
  • 不指定屬性名:打印出對(duì)象的所有屬性和其值

matplotlib的整個(gè)圖表為一個(gè)Figure對(duì)象,此對(duì)象在調(diào)用plt.figure函數(shù)時(shí)返回,我們也可以通過(guò)plt.gcf函數(shù)獲取當(dāng)前的繪圖對(duì)象:

>>> f = plt.gcf()
>>> plt.getp(f)
alpha = 1.0
animated = False
...

Figure對(duì)象有一個(gè)axes屬性,其值為AxesSubplot對(duì)象的列表,每個(gè)AxesSubplot對(duì)象代表圖表中的一個(gè)子圖,前面所繪制的圖表只包含一個(gè)子圖,當(dāng)前子圖也可以通過(guò)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對(duì)象有很多屬性,例如它的lines屬性為此子圖所包括的 Line2D 對(duì)象列表:

>>> alllines = plt.getp(plt.gca(), "lines")
>>> alllines
<a list of 3 Line2D objects>
>>> alllines[0] == line # 其中的第一條曲線就是最開(kāi)始繪制的那條曲線
True

通過(guò)這種方法我們可以很容易地查看對(duì)象的屬性和它們之間的包含關(guān)系,找到需要配置的屬性。

5.2 繪制多軸圖

一個(gè)繪圖對(duì)象(figure)可以包含多個(gè)軸(axis),在Matplotlib中用軸表示一個(gè)繪圖區(qū)域,可以將其理解為子圖。上面的第一個(gè)例子中,繪圖對(duì)象只包括一個(gè)軸,因此只顯示了一個(gè)軸(子圖)。我們可以使用subplot函數(shù)快速繪制有多個(gè)軸的圖表。subplot函數(shù)的調(diào)用形式如下:

subplot(numRows, numCols, plotNum)

subplot將整個(gè)繪圖區(qū)域等分為numRows行 * numCols列個(gè)子區(qū)域,然后按照從左到右,從上到下的順序?qū)γ總€(gè)子區(qū)域進(jìn)行編號(hào),左上的子區(qū)域的編號(hào)為1。如果numRows,numCols和plotNum這三個(gè)數(shù)都小于10的話,可以把它們縮寫(xiě)為一個(gè)整數(shù),例如subplot(323)和subplot(3,2,3)是相同的。subplot在plotNum指定的區(qū)域中創(chuàng)建一個(gè)軸對(duì)象。如果新創(chuàng)建的軸和之前創(chuàng)建的軸重疊的話,之前的軸將被刪除。

下面的程序創(chuàng)建3行2列共6個(gè)軸,通過(guò)axisbg參數(shù)給每個(gè)軸設(shè)置不同的背景顏色。

for idx, color in enumerate("rgbyck"):
    plt.subplot(320+idx+1, axisbg=color)
plt.show()
_images/pyplot_subplot01.png

圖5.2 用subplot函數(shù)將Figure分為六個(gè)子圖區(qū)域

如果希望某個(gè)軸占據(jù)整個(gè)行或者列的話,可以如下調(diào)用subplot:

plt.subplot(221) # 第一行的左圖
plt.subplot(222) # 第一行的右圖
plt.subplot(212) # 第二整行
plt.show()
_images/pyplot_subplot02.png

圖5.3 將Figure分為三個(gè)子圖區(qū)域

當(dāng)繪圖對(duì)象中有多個(gè)軸的時(shí)候,可以通過(guò)工具欄中的Configure Subplots按鈕,交互式地調(diào)節(jié)軸之間的間距和軸與邊框之間的距離。如果希望在程序中調(diào)節(jié)的話,可以調(diào)用subplots_adjust函數(shù),它有l(wèi)eft, right, bottom, top, wspace, hspace等幾個(gè)關(guān)鍵字參數(shù),這些參數(shù)的值都是0到1之間的小數(shù),它們是以繪圖區(qū)域的寬高為1進(jìn)行正規(guī)化之后的坐標(biāo)或者長(zhǎng)度。

5.3 配置文件

一幅圖有許多需要配置的屬性,例如顏色、字體、線型等等。我們?cè)诶L圖時(shí),并沒(méi)有一一對(duì)這些屬性進(jìn)行配置,許多都直接采用了Matplotlib的缺省配置。Matplotlib將缺省配置保存在一個(gè)文件中,通過(guò)更改這個(gè)文件,我們可以修改這些屬性的缺省值。

Matplotlib 使用配置文件 matplotlibrc 時(shí)的搜索順序如下:

  • 當(dāng)前路徑 : 程序的當(dāng)前路徑
  • 用戶配置路徑 : 通常為 HOME/.matplotlib/,可以通過(guò)環(huán)境變量MATPLOTLIBRC修改
  • 系統(tǒng)配置路徑 : 保存在 matplotlib的安裝目錄下的 mpl-data 下

通過(guò)下面的語(yǔ)句可以獲取用戶配置路徑:

>>> import matplotlib
>>> matplotlib.get_configdir()
'C:\\Documents and Settings\\zhang\\.matplotlib'

通過(guò)下面的語(yǔ)句可以獲得目前使用的配置文件的路徑:

>>> import matplotlib
>>> matplotlib.matplotlib_fname()
'C:\\Python26\\lib\\site-packages\\matplotlib\\mpl-data\\matplotlibrc'

由于在當(dāng)前路徑和用戶配置路徑中都沒(méi)有找到位置文件,因此最后使用的是系統(tǒng)配置路徑下的配置文件。如果你將matplotlibrc復(fù)制一份到腳本的當(dāng)前目錄下:

>>> import os
>>> os.getcwd()
'C:\\zhang\\doc'

復(fù)制配置文件之后再運(yùn)行:

>>> matplotlib.matplotlib_fname()
'C:\\zhang\\doc\\matplotlibrc'

如果你用文本編輯器打開(kāi)此配置文件的話,你會(huì)發(fā)現(xiàn)它實(shí)際上是定義了一個(gè)字典。為了對(duì)眾多的配置進(jìn)行區(qū)分,關(guān)鍵字可以用點(diǎn)分開(kāi)。

配置文件的讀入可以使用 rc_params 函數(shù),它返回一個(gè)配置字典:

>>> matplotlib.rc_params()
{'agg.path.chunksize': 0,
 'axes.axisbelow': False,
 'axes.edgecolor': 'k',
 'axes.facecolor': 'w',
 ... ...

在matplotlib模塊載入的時(shí)候會(huì)調(diào)用rc_params,并把得到的配置字典保存到rcParams變量中:

>>> matplotlib.rcParams
{'agg.path.chunksize': 0,
'axes.axisbelow': False,
... ...

matplotlib將使用rcParams中的配置進(jìn)行繪圖。用戶可以直接修改此字典中的配置,所做的改變會(huì)反映到此后所繪制的圖中。例如下面的腳本所繪制的線將帶有圓形的點(diǎn)標(biāo)識(shí)符:

>>> matplotlib.rcParams["lines.marker"] = "o"
>>> import pylab
>>> pylab.plot([1,2,3])
>>> pylab.show()

為了方便配置,可以使用rc函數(shù),下面的例子同時(shí)配置點(diǎn)標(biāo)識(shí)符、線寬和顏色:

>>> matplotlib.rc("lines", marker="x", linewidth=2, color="red")

如果希望恢復(fù)到缺省的配置(matplotlib載入時(shí)從配置文件讀入的配置)的話,可以調(diào)用 rcdefaults 函數(shù)。

>>> matplotlib.rcdefaults()

如果手工修改了配置文件,希望重新從配置文件載入最新的配置的話,可以調(diào)用:

>>> matplotlib.rcParams.update( matplotlib.rc_params() )

5.4 Artist對(duì)象

matplotlib API包含有三層:

  • backend_bases.FigureCanvas : 圖表的繪制領(lǐng)域
  • backend_bases.Renderer : 知道如何在FigureCanvas上如何繪圖
  • artist.Artist : 知道如何使用Renderer在FigureCanvas上繪圖

FigureCanvas和Renderer需要處理底層的繪圖操作,例如使用wxPython在界面上繪圖,或者使用PostScript繪制PDF。Artist則處理所有的高層結(jié)構(gòu),例如處理圖表、文字和曲線等的繪制和布局。通常我們只和Artist打交道,而不需要關(guān)心底層的繪制細(xì)節(jié)。

Artists分為簡(jiǎn)單類型和容器類型兩種。簡(jiǎn)單類型的Artists為標(biāo)準(zhǔn)的繪圖元件,例如Line2D、 Rectangle、 Text、AxesImage 等等。而容器類型則可以包含許多簡(jiǎn)單類型的Artists,使它們組織成一個(gè)整體,例如Axis、 Axes、Figure等。

直接使用Artists創(chuàng)建圖表的標(biāo)準(zhǔn)流程如下:

  • 創(chuàng)建Figure對(duì)象
  • 用Figure對(duì)象創(chuàng)建一個(gè)或者多個(gè)Axes或者Subplot對(duì)象
  • 調(diào)用Axies等對(duì)象的方法創(chuàng)建各種簡(jiǎn)單類型的Artists

下面首先調(diào)用pyplot.figure輔助函數(shù)創(chuàng)建Figure對(duì)象,然后調(diào)用Figure對(duì)象的add_axes方法在其中創(chuàng)建一個(gè)Axes對(duì)象,add_axes的參數(shù)是一個(gè)形如[left, bottom, width, height]的列表,這些數(shù)值分別指定所創(chuàng)建的Axes對(duì)象相對(duì)于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)建一條曲線,并且返回此曲線對(duì)象(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是一個(gè)為包含ax的所有曲線的列表,后續(xù)的ax.plot調(diào)用會(huì)往此列表中添加新的曲線。如果想刪除某條曲線的話,直接從此列表中刪除即可。

Axes對(duì)象還包括許多其它的Artists對(duì)象,例如我們可以通過(guò)調(diào)用set_xlabel設(shè)置其X軸上的標(biāo)題:

>>> ax.set_xlabel("time")

如果我們查看set_xlabel的源代碼的話,會(huì)發(fā)現(xiàn)它是通過(guò)調(diào)用下面的語(yǔ)句實(shí)現(xiàn)的:

self.xaxis.set_label_text(xlabel)

如果我們一直跟蹤下去,會(huì)發(fā)現(xiàn)Axes的xaxis屬性是一個(gè)XAxis對(duì)象:

>>> ax.xaxis
<matplotlib.axis.XAxis object at 0x06343230>

XAxis的label屬性是一個(gè)Text對(duì)象:

>>> ax.xaxis.label
<matplotlib.text.Text object at 0x06343290>

而Text對(duì)象的_text屬性為我們?cè)O(shè)置的值:

>>> ax.xaxis.label._text
'time'

這些對(duì)象都是Artists,因此也可以調(diào)用它們的屬性獲取函數(shù)來(lái)獲得相應(yīng)的屬性:

>>> ax.xaxis.label.get_text()
'time'

5.4.1 Artist的屬性

圖表中的每個(gè)元素都用一個(gè)matplotlib的Artist對(duì)象表示,而每個(gè)Artist對(duì)象都有一大堆屬性控制其顯示效果。例如Figure對(duì)象和Axes對(duì)象都有patch屬性作為其背景,它的值是一個(gè)Rectangle對(duì)象。通過(guò)設(shè)置此它的一些屬性可以修改Figrue圖表的背景顏色或者透明度等屬性,下面的例子將圖表的背景顏色設(shè)置為綠色:

>>> fig = plt.figure()
>>> fig.show()
>>> fig.patch.set_color("g")
>>> fig.canvas.draw()

patch的color屬性通過(guò)set_color函數(shù)進(jìn)行設(shè)置,屬性修改之后并不會(huì)立即反映到圖表的顯示上,還需要調(diào)用fig.canvas.draw()函數(shù)才能夠更新顯示。

下面是Artist對(duì)象都具有的一些屬性:

  • alpha : 透明度,值在0到1之間,0為完全透明,1為完全不透明
  • animated : 布爾值,在繪制動(dòng)畫(huà)效果時(shí)使用
  • axes : 此Artist對(duì)象所在的Axes對(duì)象,可能為None
  • clip_box : 對(duì)象的裁剪框
  • clip_on : 是否裁剪
  • clip_path : 裁剪的路徑
  • contains : 判斷指定點(diǎn)是否在對(duì)象上的函數(shù)
  • figure : 所在的Figure對(duì)象,可能為None
  • label : 文本標(biāo)簽
  • picker : 控制Artist對(duì)象選取
  • transform : 控制偏移旋轉(zhuǎn)
  • visible : 是否可見(jiàn)
  • zorder : 控制繪圖順序

Artist對(duì)象的所有屬性都通過(guò)相應(yīng)的 get_* 和 set_* 函數(shù)進(jìn)行讀寫(xiě),例如下面的語(yǔ)句將alpha屬性設(shè)置為當(dāng)前值的一半:

>>> fig.set_alpha(0.5*fig.get_alpha())

如果你想用一條語(yǔ)句設(shè)置多個(gè)屬性的話,可以使用set函數(shù):

>>> fig.set(alpha=0.5, zorder=2)

使用前面介紹的 matplotlib.pyplot.getp 函數(shù)可以方便地輸出Artist對(duì)象的所有屬性名和值。

>>> plt.getp(fig.patch)
    aa = True
    alpha = 1.0
    animated = False
    antialiased or aa = True
    ... ...

5.4.2 Figure容器

現(xiàn)在我們知道如何觀察和修改已知的某個(gè)Artist對(duì)象的屬性,接下來(lái)要解決如何找到指定的Artist對(duì)象。前面我們介紹過(guò)Artist對(duì)象有容器類型和簡(jiǎn)單類型兩種,這一節(jié)讓我們來(lái)詳細(xì)看看容器類型的內(nèi)容。

最大的Artist容器是matplotlib.figure.Figure,它包括組成圖表的所有元素。圖表的背景是一個(gè)Rectangle對(duì)象,用Figure.patch屬性表示。當(dāng)你通過(guò)調(diào)用add_subplot或者add_axes方法往圖表中添加軸(子圖時(shí)),這些子圖都將添加到Figure.axes屬性中,同時(shí)這兩個(gè)方法也返回添加進(jìn)axes屬性的對(duì)象,注意返回值的類型有所不同,實(shí)際上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對(duì)象內(nèi)部保存有當(dāng)前軸的信息,因此不建議直接對(duì)Figure.axes屬性進(jìn)行列表操作,而應(yīng)該使用add_subplot, add_axes, delaxes等方法進(jìn)行添加和刪除操作。但是使用for循環(huán)對(duì)axes中的每個(gè)元素進(jìn)行操作是沒(méi)有問(wèn)題的,下面的語(yǔ)句打開(kāi)所有子圖的柵格。

>>> for ax in fig.axes: ax.grid(True)

Figure對(duì)象可以擁有自己的文字、線條以及圖像等簡(jiǎn)單類型的Artist。缺省的坐標(biāo)系統(tǒng)為像素點(diǎn),但是可以通過(guò)設(shè)置Artist對(duì)象的transform屬性修改坐標(biāo)系的轉(zhuǎn)換方式。最常用的Figure對(duì)象的坐標(biāo)系是以左下角為坐標(biāo)原點(diǎn)(0,0),右上角為坐標(biāo)(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()
_images/pyplot_artist01.png

圖5.4 在Figure對(duì)象中手工繪制直線

注意為了讓所創(chuàng)建的Line2D對(duì)象使用fig的坐標(biāo),我們將fig.TransFigure賦給Line2D對(duì)象的transform屬性;為了讓Line2D對(duì)象知道它是在fig對(duì)象中,我們還設(shè)置其figure屬性為fig;最后還需要將創(chuàng)建的兩個(gè)Line2D對(duì)象添加到fig.lines屬性中去。

Figure對(duì)象有如下屬性包含其它的Artist對(duì)象:

  • axes : Axes對(duì)象列表
  • patch : 作為背景的Rectangle對(duì)象
  • images : FigureImage對(duì)象列表,用來(lái)顯示圖片
  • legends : Legend對(duì)象列表
  • lines : Line2D對(duì)象列表
  • patches : patch對(duì)象列表
  • texts : Text對(duì)象列表,用來(lái)顯示文字

5.4.3 Axes容器

Axes容器是整個(gè)matplotlib庫(kù)的核心,它包含了組成圖表的眾多Artist對(duì)象,并且有許多方法函數(shù)幫助我們創(chuàng)建、修改這些對(duì)象。和Figure一樣,它有一個(gè)patch屬性作為背景,當(dāng)它是笛卡爾坐標(biāo)時(shí),patch屬性是一個(gè)Rectangle對(duì)象,而當(dāng)它是極坐標(biāo)時(shí),patch屬性則是Circle對(duì)象。例如下面的語(yǔ)句設(shè)置Axes對(duì)象的背景顏色為綠色:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.patch.set_facecolor("green")

當(dāng)你調(diào)用Axes的繪圖方法(例如plot),它將創(chuàng)建一組Line2D對(duì)象,并將所有的關(guān)鍵字參數(shù)傳遞給這些Line2D對(duì)象,并將它們添加進(jìn)Axes.lines屬性中,最后返回所創(chuàng)建的Line2D對(duì)象列表:

>>> 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返回的是一個(gè)Line2D對(duì)象的列表,因?yàn)槲覀兛梢詡鬟f多組X,Y軸的數(shù)據(jù),一次繪制多條曲線。

與plot方法類似,繪制直方圖的方法bar和繪制柱狀統(tǒng)計(jì)圖的方法hist將創(chuàng)建一個(gè)Patch對(duì)象的列表,每個(gè)元素實(shí)際上都是Patch的子類Rectangle,并且將所創(chuàng)建的Patch對(duì)象都添加進(jìn)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>

一般我們不會(huì)直接對(duì)Axes.lines或者Axes.patches屬性進(jìn)行操作,而是調(diào)用add_line或者add_patch等方法,這些方法幫助我們完成許多屬性設(shè)置工作:

>>> 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添加進(jìn)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()
... # 太長(zhǎng),省略
>>> ax.transData
... # 太長(zhǎng),省略
>>> ax.get_xlim() # ax的X軸范圍為0到1,無(wú)法顯示完整的rect
(0.0, 1.0)
>>> ax.dataLim._get_bounds() # 數(shù)據(jù)的范圍和rect的大小一致
(1.0, 1.0, 5.0, 12.0)
>>> ax.autoscale_view() # 自動(dòng)調(diào)整坐標(biāo)軸范圍
>>> ax.get_xlim() # 于是X軸可以完整顯示rect
(1.0, 6.0)
>>> plt.show()

通過(guò)上面的例子我們可以看出,add_patch方法幫助我們?cè)O(shè)置了rect的axes和transform屬性。

下面詳細(xì)列出Axes包含各種Artist對(duì)象的屬性:

  • artists : Artist對(duì)象列表
  • patch : 作為Axes背景的Patch對(duì)象,可以是Rectangle或者Circle
  • collections : Collection對(duì)象列表
  • images : AxesImage對(duì)象列表
  • legends : Legend對(duì)象列表
  • lines : Line2D對(duì)象列表
  • patches : Patch對(duì)象列表
  • texts : Text對(duì)象列表
  • xaxis : XAxis對(duì)象
  • yaxis : YAxis對(duì)象

下面列出Axes的創(chuàng)建Artist對(duì)象的方法:

Axes的方法 所創(chuàng)建的對(duì)象 添加進(jìn)的列表
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)為例,驗(yàn)證一下:

>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> t = ax.scatter(np.random.rand(20), np.random.rand(20))
>>> t # 返回值為CircleCollection對(duì)象
<matplotlib.collections.CircleCollection object at 0x06004230>
>>> ax.collections # 返回的對(duì)象已經(jīng)添加進(jìn)了collections列表中
[<matplotlib.collections.CircleCollection object at 0x06004230>]
>>> fig.show()
>>> t.get_sizes() # 獲得Collection的點(diǎn)數(shù)
20
_images/pyplot_artist02.png

圖5.5 用scatter函數(shù)繪制散列圖

5.4.4 Axis容器

Axis容器包括坐標(biāo)軸上的刻度線、刻度文本、坐標(biāo)網(wǎng)格以及坐標(biāo)軸標(biāo)題等內(nèi)容。刻度包括主刻度和副刻度,分別通過(guò)Axis.get_major_ticks和Axis.get_minor_ticks方法獲得。每個(gè)刻度線都是一個(gè)XTick或者YTick對(duì)象,它包括實(shí)際的刻度線和刻度文本。為了方便訪問(wèn)刻度線和文本,Axis對(duì)象提供了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() # 獲得刻度標(biāo)簽列表
<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>

獲得刻度線或者刻度標(biāo)簽之后,可以設(shè)置其各種屬性,下面設(shè)置刻度線為綠色粗線,文本為紅色并且旋轉(zhuǎn)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)

最終的結(jié)果圖如下:

_images/pyplot_axis01.png

圖5.6 手工配置X軸的刻度線和刻度文本的樣式

上面的例子中,獲得的副刻度線列表為空,這是因?yàn)橛糜谟?jì)算副刻度的對(duì)象缺省為NullLocator,它不產(chǎn)生任何刻度線;而計(jì)算主刻度的對(duì)象為AutoLocator,它會(huì)根據(jù)當(dāng)前的縮放等配置自動(dòng)計(jì)算刻度的位置:

>>> axis.get_minor_locator() # 計(jì)算副刻度的對(duì)象
<matplotlib.ticker.NullLocator instance at 0x0A014300>
>>> axis.get_major_locator() # 計(jì)算主刻度的對(duì)象
<matplotlib.ticker.AutoLocator instance at 0x09281B20>

我們可以使用程序?yàn)锳xis對(duì)象設(shè)置不同的Locator對(duì)象,用來(lái)手工設(shè)置刻度的位置;設(shè)置Formatter對(duì)象用來(lái)控制刻度文本的顯示。下面的程序設(shè)置X軸的主刻度為pi/4,副刻度為pi/20,并且主刻度上的文本以pi為單位:

# -*- coding: utf-8 -*-
import matplotlib.pyplot as pl
from matplotlib.ticker import MultipleLocator, FuncFormatter
import numpy as np
x = 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ù)值轉(zhuǎn)換為以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)

# 設(shè)置兩個(gè)坐標(biāo)軸的范圍
pl.ylim(-1.5,1.5)
pl.xlim(0, np.max(x))

# 設(shè)置圖的底邊距
pl.subplots_adjust(bottom = 0.15)

pl.grid() #開(kāi)啟網(wǎng)格

# 主刻度為pi/4
ax.xaxis.set_major_locator( MultipleLocator(np.pi/4) )

# 主刻度文本用pi_formatter函數(shù)計(jì)算
ax.xaxis.set_major_formatter( FuncFormatter( pi_formatter ) )

# 副刻度為pi/20
ax.xaxis.set_minor_locator( MultipleLocator(np.pi/20) )

# 設(shè)置刻度文本的大小
for tick in ax.xaxis.get_major_ticks():
    tick.label1.set_fontsize(16)
pl.show()

關(guān)于刻度的定位和文本格式的東西都在matplotlib.ticker中定義,程序中使用到如下兩個(gè)類:

  • MultipleLocator : 以指定值的整數(shù)倍為刻度放置刻度線
  • FuncFormatter : 使用指定的函數(shù)計(jì)算刻度文本,他會(huì)傳遞給所指定的函數(shù)兩個(gè)參數(shù):刻度值和刻度序號(hào),程序中通過(guò)比較笨的辦法計(jì)算出刻度值所對(duì)應(yīng)的刻度文本

此外還有很多預(yù)定義的Locator和Formatter類,詳細(xì)內(nèi)容請(qǐng)參考相應(yīng)的API文檔。

_images/pyplot_axis02.png

圖5.7 手工配置X軸的刻度線的位置和文本,并開(kāi)啟副刻度


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多