python下Matplotlib繪圖案例與常見設定簡介

wangsys發表於2021-09-09

首先一幅Matplotlib的影像組成部分介紹。

基本構成

在matplotlib中,整個影像為一個Figure物件。在Figure物件中可以包含一個或者多個Axes物件。每個Axes(ax)物件都是一個擁有自己座標系統的繪圖區域。所屬關係如下: 
圖片描述

詳解影像各個元件

下面以一個直線圖來詳解影像內部各個元件內容: 
圖片描述 
其中:title為影像標題,Axis為座標軸, Label為座標軸標註,Tick為刻度線,Tick Label為刻度註釋。各個物件關係可以梳理成以下內容: 
圖片描述

部分設定詳解

影像中所有物件均來自於Artist的基類。 
上面基本介紹清楚了影像中各個部分的基本關係,下面著重講一下幾個部分的詳細的設定。 
一個”Figure”意味著使用者互動的整個視窗。在這個figure中容納著”subplots”。 
當我們呼叫plot時,matplotlib會呼叫gca()獲取當前的axes繪圖區域,而且gca反過來呼叫gcf()來獲得當前的figure。如果figure為空,它會自動呼叫figure()生成一個figure, 嚴格的講,是生成subplots(111)。 
圖片描述

子圖Subplots

注意:其中各個引數也可以用逗號,分隔開。第一個引數代表子圖的行數;第二個引數代表該行影像的列數; 第三個引數代表每行的第幾個影像。

plt.subplot(221) # 第一行的左圖 
plt.subplot(222) # 第一行的右圖 
plt.subplot(212) # 第二整行 
plt.show() 
圖片描述
參考案例

另外:fig, ax = plt.subplots(2,2),其中引數分別代表子圖的行數和列數,一共有 2x2 個影像。函式返回一個figure影像和一個子圖ax的array列表。 
補充:gridspec命令可以對子圖區域劃分提供更靈活的配置。

子影像統一標題設定

效果如下(subplot row i): 
思路其實建立整個的子影像,然後將影像的刻度、標註等部分作不顯示設定,僅僅顯示影像的 title。 
圖片描述
案例程式碼

import matplotlib.pyplot as plt

fig, big_axes = plt.subplots(figsize=(15.0, 15.0) , nrows=3, ncols=1, sharey=True) 

for row, big_ax in enumerate(big_axes, start=1):
    big_ax.set_title("Subplot row %s n" % row, fontsize=16)

    # Turn off axis lines and ticks of the big subplot 
    # obs alpha is 0 in RGBA string!
    big_ax.tick_params(labelcolor=(0,0,0,0), top='off', bottom='off', left='off', right='off')
    # removes the white frame
    big_ax._frameon = Falsefor i in range(1,10):
    ax = fig.add_subplot(3,3,i)
    ax.set_title('Plot title ' + str(i))


fig.set_facecolor('w')
plt.tight_layout()
plt.show()    123456789101112131415161718192021
刻度Tick Locators

Tick Locators 控制著 ticks 的位置。比如下面:

ax = plt.gca()
ax.xaxis.set_major_locator(eval(locator))12

一些不同型別的locators:

圖片描述 
案例程式碼:

import numpy as npimport matplotlib.pyplot as pltdef tickline():plt.xlim(0, 10), plt.ylim(-1, 1), plt.yticks([])
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.yaxis.set_ticks_position('none')
ax.xaxis.set_minor_locator(plt.MultipleLocator(0.1))
ax.plot(np.arange(11), np.zeros(11))return ax

locators = ['plt.NullLocator()','plt.MultipleLocator(1.0)','plt.FixedLocator([0, 2, 8, 9, 10])','plt.IndexLocator(3, 1)','plt.LinearLocator(5)','plt.LogLocator(2, [1.0])','plt.AutoLocator()',
]

n_locators = len(locators)

size = 512, 40 * n_locators
dpi = 72.0figsize = size[0] / float(dpi), size[1] / float(dpi)
fig = plt.figure(figsize=figsize, dpi=dpi)
fig.patch.set_alpha(0)for i, locator in enumerate(locators):
plt.subplot(n_locators, 1, i + 1)
ax = tickline()
ax.xaxis.set_major_locator(eval(locator))
plt.text(5, 0.3, locator[3:], ha='center')

plt.subplots_adjust(bottom=.01, top=.99, left=.01, right=.99)
plt.show()1234567891011121314151617181920212223242526272829303132333435363738394041424344

所有這些locators均來自於基類matplotlib.ticker.Locator。你可以透過繼承該基類建立屬於自己的locator樣式。同時matplotlib也提供了特殊的日期locator, 位於matplotlib.date 
基類matplotlib.ticker.Locator參考文獻

刻度和標註特殊設定

描述如下:在X軸標出一些重要的刻度點,當然實現方式有兩種:直接在X軸上標註和透過註釋annotate的形式標註在合適的位置。 
其中第一種的實現並不是很合適,此處為了學習的目的一併說明下。

先說第一種: 
圖片描述 
正常X軸標註不會是這樣的,為了說明此問題特意標註成這樣,如此看來 0.3 和 0.4的標註重疊了,當然瞭解決重疊的問題可以透過改變figure 的size實現,顯然此處並不想這樣做。

怎麼解決呢,那就在 0.3 和 0.4之間再設定一個刻度,有了空間後不顯示即可。

程式碼如下:

# -*- coding: utf-8 -*-import matplotlib.pyplot as plt
fig = plt.figure(figsize=(3, 3))  
ax = fig.add_subplot(1, 1, 1, frameon=False)
ax.set_xlim(-0.015, 1.515)
ax.set_ylim(-0.01, 1.01)
ax.set_xticks([0, 0.3, 0.4, 1.0, 1.5])#增加0.35處的刻度並不標註文字,然後重新標註0.3和0.4處文字ax.set_xticklabels([0.0, "", "", 1.0, 1.5])
ax.set_xticks([0.35], minor=True)
ax.set_xticklabels(["0.3 0.4"], minor=True)#上述設定只是增加空間,並不想看到刻度的標註,因此次刻度線不予顯示。for line in ax.xaxis.get_minorticklines():
line.set_visible(False)

ax.grid(True)
plt.show()123456789101112131415161718

最終影像形式如下: 
圖片描述 
當然最合理的方式是採用註釋的形式,比如: 
圖片描述 
案例程式碼如下:

# -*- coding: utf-8 -*-import matplotlib.pyplot as pltimport numpy as np# Plot a sinc functiondelta=2.0x=np.linspace(-10,10,100)
y=np.sinc(x-delta)# Mark deltaplt.axvline(delta,ls="--",color="r")
plt.annotate(r"$delta$",xy=(delta+0.2,-0.2),color="r",size=15)
plt.plot(x,y)1234567891011121314
增加X軸與Y軸間的間隔,向右移動X軸標註

顯示效果對比:

設定前: 
圖片描述 
設定後: 
圖片描述

上圖程式碼如下:

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

fig = plt.figure()
ax = fig.add_subplot(111)
plot_data=[1.7,1.7,1.7,1.54,1.52]
xdata = range(len(plot_data))
labels = ["2009-June","2009-Dec","2010-June","2010-Dec","2011-June"]
ax.plot(xdata,plot_data,"b-")
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels)
ax.set_yticks([1.4,1.6,1.8])# grow the y axis down by 0.05ax.set_ylim(1.35, 1.8)# expand the x axis by 0.5 at two endsax.set_xlim(-0.5, len(labels)-0.5)

plt.show()1234567891011121314151617181920
移動刻度標註

上圖說明需求: 
圖片描述
透過設定 來控制標註的左右位置:

for tick in ax2.xaxis.get_majorticklabels():    tick.set_horizontalalignment("left")12

當然標註文字的上下位置也是可以控制的,比如:

ax2.xaxis.get_majorticklabels()[2].set_y(-.1)1

當然控制刻度標註的上下位置也可以用labelpad引數進行設定:

pl.xlabel("...", labelpad=20) 
或:
ax.xaxis.labelpad = 20   123

具體設定請查閱官方文件,完整的程式碼如下:

# -*- coding: utf-8 -*-import matplotlib.pyplot as plt
import numpy as np
import datetime# my fake datadates = np.array([datetime.datetime(2000,1,1) + datetime.timedelta(days=i) for i in range(365*5)])
data = np.sin(np.arange(365*5)/365.0*2*np.pi - 0.25*np.pi) + np.random.rand(365*5) /3# creates fig with 2 subplotsfig = plt.figure(figsize=(10.0, 6.0))
ax = plt.subplot2grid((2,1), (0, 0))
ax2 = plt.subplot2grid((2,1), (1, 0))## plot datesax2.plot_date( dates, data )# rotates labels plt.setp( ax2.xaxis.get_majorticklabels(), rotation=-45 ) 

# shift labels to the rightfor tick in ax2.xaxis.get_majorticklabels():
    tick.set_horizontalalignment("right")

plt.tight_layout()
plt.show()1234567891011121314151617181920212223242526
調整影像邊緣及影像間的空白間隔plt.tight_layout()

影像外部邊緣的調整可以使用plt.tight_layout()進行自動控制,此方法不能夠很好的控制影像間的間隔。 
如果想同時控制影像外側邊緣以及影像間的空白區域,使用命令:

plt.subplots_adjust(left=0.2, bottom=0.2, right=0.8, top=0.8,hspace=0.2, wspace=0.3)1
影像的大小設定

如果已經存在figure物件,可以透過以下程式碼設定尺寸大小:

f.set_figheight(15)
f.set_figwidth(15)12

若果透過.sublots()命令來建立新的figure物件, 可以透過設定figsize引數達到目的。

f, axs = plt.subplots(2,2,figsize=(15,15))


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3244/viewspace-2803310/,如需轉載,請註明出處,否則將追究法律責任。

相關文章