在這篇教學文章中,我們將介紹 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-3
,y
軸的範圍是1-4
。如果為plot()
命令提供單個列表或數組,則matplotlib假定它是一系列y
值,並自動生成x
值。由於python範圍以0
開頭,因此默認的x
和y
向量具有相同的長度,但從0
開始。因此x
數據為[0,1,2,3]
。
plot()
是一個多功能命令,將採用任意數量的參數。例如,要繪製x
與y
的關係,您可以使用以下命令:
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
得到的繪圖結果如下 -
格式化繪圖的樣式
對於每對x
,y
對的參數,有一個可選的第三個參數,它是指示繪圖的顏色和線型的格式字串。格式字串的字母和符號來自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.recarray
或pandas.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()
執行上面示例代碼,得到以下結果 -
控制線屬性
行可以設置許多屬性:linewidth
,dash style
,antialiased
等; 請參閱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()
命令指定numrows
,numcols
,plot_number
,其中plot_number
的範圍從1
到numrows * numcols
。如果numrows * numcols <10
,則subplot
命令中的逗號是可選的。因此子圖(211)與子圖(2,1,1)相同。
可以創建任意數量的子圖和軸。如果要手動放置軸,即不在矩形網格上,請使用axes()
命令,該命令用於將位置指定為軸([left,bottom,width,height]),其中所有值均為小數 (0
到1
)座標。
可以使用具有增加的圖號的多個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()
執行上面示例代碼,得到以下結果 -