Matplotlib pyplot教學


在這篇教學文章中,我們將介紹 pyplot 介面。

pyplot簡介

matplotlib.pyplot是命令樣式函式的集合,使matplotlib像MATLAB一樣工作。每個pyplot函式對圖形進行一些更改。例如,建立圖形,在圖形中建立繪圖區域,繪製繪圖區域中的某些線條,使用標籤裝飾圖形等。

matplotlib.pyplot中,各種狀態在函式呼叫中保留,以便跟蹤當前圖形和繪圖區域等內容,並且繪圖函式指向當前軸(請注意「軸」在此處以及在大多數位置 文件是指圖形的軸部分,而不是多個軸的嚴格數學術語。)

注意 - pyplot API通常不如物件導向的API靈活。在此處看到的大多數函式呼叫也可以作為Axes物件中的方法呼叫。我們建議您閱讀瀏覽教學和範例以了解其工作原理。

使用pyplot生成視覺化,非常簡單:

#! /usr/bin/env python
#coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
import math
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei'] # 
plt.rcParams['axes.unicode_minus'] = False   
# 原文出自【易百教學】,商業轉載請聯絡作者獲得授權,非商業請保留原文連結。

plt.plot([1, 2, 3, 4])
plt.ylabel('簡單數位序列')
plt.show()

執行上面範例程式碼,得到以下結果 -

你可能想知道為什麼x軸的範圍是0-3y軸的範圍是1-4。如果為plot()命令提供單個列表或陣列,則matplotlib假定它是一系列y值,並自動生成x值。由於python範圍以0開頭,因此預設的xy向量具有相同的長度,但從0開始。因此x資料為[0,1,2,3]

plot()是一個多功能命令,將採用任意數量的引數。例如,要繪製xy的關係,您可以使用以下命令:

plt.plot([1, 2, 3, 4], [1, 4, 9, 16])

得到的繪圖結果如下 -

格式化繪圖的樣式

對於每對xy對的引數,有一個可選的第三個引數,它是指示繪圖的顏色和線型的格式字串。格式字串的字母和符號來自MATLAB,可以將顏色字串與線型字串連線起來。預設格式字串為「b-」,為藍色實線。例如,要用紅色圓圈繪製上述內容,使用以下程式碼:

plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')
plt.axis([0, 6, 0, 20])
plt.show()

上面程式碼將得到以下結果 -

有關線型和格式字串的完整列表,請參閱plot()文件。上面範例例中的axis()命令採用[xmin,xmax,ymin,ymax]列表並指定軸的視口。

如果matplotlib僅限於使用列表,那麼數位處理將毫無用處。通常使用numpy陣列。實際上,所有序列都在內部轉換為numpy陣列。下面的範例說明了使用陣列在一個命令中繪製具有不同格式樣式的多行。

import numpy as np

# evenly sampled time at 200ms intervals
t = np.arange(0., 5., 0.2)

# red dashes, blue squares and green triangles
plt.plot(t, t, 'r--', t, t**2, 'bs', t, t**3, 'g^')
plt.show()

執行上面程式碼將得到以下結果 -

使用關鍵字字串繪圖

在某些情況下,可以使用字串存取特定變數的格式的資料。例如,使用numpy.recarraypandas.DataFrame

Matplotlib用於使用data關鍵字引數提供此類物件。如果提供,那麼可以生成包含與這些變數對應的字串的繪圖。

data = {'a': np.arange(50),
        'c': np.random.randint(0, 50, 50),
        'd': np.random.randn(50)}
data['b'] = data['a'] + 10 * np.random.randn(50)
data['d'] = np.abs(data['d']) * 100

plt.scatter('a', 'b', c='c', s='d', data=data)
plt.xlabel('entry a')
plt.ylabel('entry b')
plt.show()

執行上面程式碼將得到以下結果 -

用分類變數繪圖

也可以使用分類變數建立繪圖。Matplotlib可將分類變數直接傳遞給許多繪圖函式。例如:

#! /usr/bin/env python
#coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
import math
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei'] # 
plt.rcParams['axes.unicode_minus'] = False   
# 原文出自【易百教學】,商業轉載請聯絡作者獲得授權,非商業請保留原文連結。

names = ['分組-A', '分組-B', '分組-C']
values = [1, 10, 100]

plt.figure(figsize=(9, 3))

plt.subplot(131)
plt.bar(names, values)
plt.subplot(132)
plt.scatter(names, values)
plt.subplot(133)
plt.plot(names, values)
plt.suptitle('分類繪圖')
plt.show()

執行上面範例程式碼,得到以下結果 -

分類繪圖

控制線屬性

行可以設定許多屬性:linewidthdash styleantialiased等; 請參閱matplotlib.lines.Line2D。有幾種方法可以用來設定線屬性 -

第1種: 使用關鍵字args

plt.plot(x, y, linewidth=2.0)

第2種: 使用Line2D範例的setter方法。plot返回Line2D物件列表; 例如,line1,line2 = plot(x1,y1,x2,y2)。在下面的程式碼中,假設只有一行,因此返回的列表的長度為1。我們使用tuple解壓縮為line,以獲取該列表的第一個元素:

line, = plt.plot(x, y, '-')
line.set_antialiased(False) # turn off antialiasing

第3種: 使用setp()命令。下面的範例使用MATLAB樣式命令在行列表上設定多個屬性。setp透明地使用物件列表或單個物件。可以使用python關鍵字引數或MATLAB樣式的字串/值對:

lines = plt.plot(x1, y1, x2, y2)
# use keyword args
plt.setp(lines, color='r', linewidth=2.0)
# or MATLAB style string value pairs
plt.setp(lines, 'color', 'r', 'linewidth', 2.0)

以下是Line2D的屬性。

屬性 值型別
alpha float
animated [True Ι False]
antialiased 或 aa [True Ι False]
clip_box 一個matplotlib.transform.Bbox範例
clip_on [True Ι False]
clip_path 一個Path範例和Transform範例
color or c 任意 matplotlib 顏色
contains 命中測試功能
dash_capstyle [‘butt’ Ι ‘round’ Ι ‘projecting’]
dash_joinstyle [‘miter’ Ι ‘round’ Ι ‘bevel’]
dashes 點的開/關墨水序列
data (np.array xdata, np.array ydata)
figure 一個 matplotlib.figure.Figure 範例
label any string
linestyle or ls [ ‘-‘ Ι ‘—‘ Ι ‘-.’ Ι ‘:’ Ι ‘steps’ Ι …]
linewidth or lw 浮點數值
marker [ ‘+’ Ι ‘,’ Ι ‘.’ Ι ‘1’ Ι ‘2’ Ι ‘3’ Ι ‘4’ ]
markeredgecolor or mec 任意 matplotlib 顏色
markeredgewidth or mew 浮點數值
markerfacecolor or mfc 任意 matplotlib 顏色
markersize or ms float
markevery [ None Ι integer Ι (startind, stride) ]
picker 用於互動式行選擇
pickradius 行選擇半徑
solid_capstyle [‘butt’ Ι ‘round’ Ι ‘projecting’]
solid_joinstyle [‘miter’ Ι ‘round’ Ι ‘bevel’]
transform matplotlib.transforms.Transform 範例
visible [True Ι False]
xdata np.array
ydata np.array
zorder 任意數位

要獲取可設定的行屬性列表,請使用一行或多行作為引數呼叫setp()函式

In [69]: lines = plt.plot([1, 2, 3])

In [70]: plt.setp(lines)
  alpha: float
  animated: [True | False]
  antialiased or aa: [True | False]
  ...snip

使用多個圖形和軸

MATLAB和pyplot具有當前圖形和當前軸的概念。所有繪圖命令都適用於當前軸。函式gca()返回當前軸(matplotlib.axes.Axes範例),gcf()返回當前數位(matplotlib.figure.Figure範例)。通常情況下,不必擔心這一點,因為它完全在後台處理。下面是一個建立兩個子圖的指令碼。

#! /usr/bin/env python
#coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
import math
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei'] # 
plt.rcParams['axes.unicode_minus'] = False   
# 原文出自【易百教學】,商業轉載請聯絡作者獲得授權,非商業請保留原文連結。

def f(t):
    return np.exp(-t) * np.cos(2*np.pi*t)

t1 = np.arange(0.0, 5.0, 0.1)
t2 = np.arange(0.0, 5.0, 0.02)

plt.figure()
plt.subplot(211)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')

plt.subplot(212)
plt.plot(t2, np.cos(2*np.pi*t2), 'r--')
plt.show()

執行上面範例程式碼,得到以下結果 -

這裡的figure()命令是可選的,因為預設情況下會建立圖(1),就像預設情況下建立子圖(111)一樣,如果不手動指定任何軸。subplot()命令指定numrowsnumcolsplot_number,其中plot_number的範圍從1numrows * numcols。如果numrows * numcols <10,則subplot命令中的逗號是可選的。因此子圖(211)與子圖(2,1,1)相同。

可以建立任意數量的子圖和軸。如果要手動放置軸,即不在矩形網格上,請使用axes()命令,該命令用於將位置指定為軸([left,bottom,width,height]),其中所有值均為小數 (01)坐標。

可以使用具有增加的圖號的多個figure()呼叫來建立多個數位。當然,每個圖形可以包含心中所需的軸和子圖:

import matplotlib.pyplot as plt
plt.figure(1)                # the first figure
plt.subplot(211)             # the first subplot in the first figure
plt.plot([1, 2, 3])
plt.subplot(212)             # the second subplot in the first figure
plt.plot([4, 5, 6])


plt.figure(2)                # a second figure
plt.plot([4, 5, 6])          # creates a subplot(111) by default

plt.figure(1)                # figure 1 current; subplot(212) still current
plt.subplot(211)             # make subplot(211) in figure1 current
plt.title('Easy as 1, 2, 3') # subplot 211 title

可以使用clf()清除當前圖形,使用cla()清除當前軸。如果發現在後台維護狀態(特別是當前影象,圖形和軸)很煩人,請不要絕望:這只是圍繞物件導向API的瘦狀態包裝器,可以使用它。

如果要製作大量的數位,還需要注意一件事:在用close()顯式關閉數位之前,數位所需的記憶體不會完全釋放。刪除對圖的所有參照,和/或使用視窗管理器來殺死螢幕上出現圖形的視窗是不夠的,因為pyplot會保持內部參照,直到呼叫close()

使用文字

text()命令可用於在任意位置新增文字,xlabel()ylabel()title()用於在指定位置新增文字。

#! /usr/bin/env python
#coding=utf-8
import matplotlib.pyplot as plt
import numpy as np
import math
import seaborn as sns

plt.rcParams['font.sans-serif'] = ['SimHei'] # 
plt.rcParams['axes.unicode_minus'] = False   
# 原文出自【易百教學】,商業轉載請聯絡作者獲得授權,非商業請保留原文連結。

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

# the histogram of the data
n, bins, patches = plt.hist(x, 50, density=1, facecolor='g', alpha=0.75)


plt.xlabel('聰明')
plt.ylabel('可能性')
plt.title('智商直方圖')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()

執行上面範例程式碼,得到以下結果 -

智商直方圖

所有text()命令都返回一個matplotlib.text.Text範例。與上面的行一樣,可以通過將關鍵字引數傳遞給文字函式或使用setp()來自定義屬性:

t = plt.xlabel('my data', fontsize=14, color='red')

在文字中使用數學表示式
matplotlib在任何文字表示式中接受TeX方程表示式。例如,要在標題中寫入表示式σi= 15,可以編寫由美元符號包圍的TeX表示式:

plt.title(r'$\sigma_i=15$')

標題字串前面的r很重要 - 它表示該字串是一個原始字串,而不是將反斜槓視為python跳脫。matplotlib有一個內建的TeX表示式解析器和布局引擎,並提供自己的數學字型。因此,您可以跨平台使用數學文字,而無需安裝TeX。對於那些安裝了LaTeX和dvipng的人,還可以使用LaTeX格式化文字並將輸出直接合併到顯示圖或儲存的postscript中。

注釋文字
上面的基本text()命令的使用將文字放在Axes上的任意位置。文字的常見用途是注釋繪圖的某些功能,annotate()方法提供幫助功能以使注釋變得容易。在註釋中,有兩點需要考慮:由引數xy表示的注釋位置和文字xytext的位置。這兩個引數都是(x,y)元組。

ax = plt.subplot(111)

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)
line, = plt.plot(t, s, lw=2)

plt.annotate('local max', xy=(2, 1), xytext=(3, 1.5),
             arrowprops=dict(facecolor='black', shrink=0.05),
             )

plt.ylim(-2, 2)
plt.show()

執行上面範例程式碼,得到以下結果 -

注釋文本

在此基本範例中,xy(箭頭提示)和xytext位置(文字位置)都在資料坐標中。可以選擇各種其他坐標系。

對數和其他非線性軸

matplotlib.pyplot不僅支援線性軸刻度,還支援對數和logit刻度。如果資料跨越許多數量級,則通常使用此方法。更改軸的比例很容易:

plt.xscale('log')

下面顯示了具有相同資料和y軸不同比例的四個圖的範例。

from matplotlib.ticker import NullFormatter  # useful for `logit` scale

# Fixing random state for reproducibility
np.random.seed(19680801)

# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))

# plot with various axes scales
plt.figure()

# linear
plt.subplot(221)
plt.plot(x, y)
plt.yscale('linear')
plt.title('linear')
plt.grid(True)


# log
plt.subplot(222)
plt.plot(x, y)
plt.yscale('log')
plt.title('log')
plt.grid(True)


# symmetric log
plt.subplot(223)
plt.plot(x, y - y.mean())
plt.yscale('symlog', linthreshy=0.01)
plt.title('symlog')
plt.grid(True)

# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
plt.title('logit')
plt.grid(True)
# Format the minor tick labels of the y-axis into empty strings with
# `NullFormatter`, to avoid cumbering the axis with too many labels.
plt.gca().yaxis.set_minor_formatter(NullFormatter())
# Adjust the subplot layout, because the logit one may take more space
# than usual, due to y-tick labels like "1 - 10^{-3}"
plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
                    wspace=0.35)

plt.show()

執行上面範例程式碼,得到以下結果 -

對數和其他非線性軸