Python數據科學手冊(4) Matplotlib數據可視化

Matplotlib 是創建在 NumPy 數組基礎上的多平臺數據可視化程序庫,能夠畫出相似 MATLAB 風格的交互式圖形。
Matplotlib 最重要的特性之一就是具備良好的操做系統兼容性和圖形顯示底層接口兼容性(graphics backend)。Matplotlib 支持幾十種圖形顯示接口與輸出格式,這使得用戶不管在哪一種操做系統上均可以輸出本身想要的圖形格式。這種跨平臺、面面俱到的特色已經成爲Matplotlib 最強大的功能之一,atplotlib 也所以吸引了大量用戶,進而造成了一個活躍的開發者團隊,晉升爲 Python 科學領域不可或缺的強大武器。python

4.1 Matplotlib經常使用技巧

4.1.1 導入Matplotlib

import matplotlib as mpl 
import matplotlib.pyplot as plt

4.1.2 設置繪圖樣式

使用 plt.style 來選擇圖形的繪圖風格。例如:shell

plt.style.use('classic')

4.1.3 如何顯示圖形

1. 在腳本中畫圖

若是在一個腳本文件中使用 Matplotlib,那麼顯示圖形的時候必須使用 plt.show()。plt.show() 會啓動一個事件循環(event loop),並找到全部當前可用的圖形對象,而後打開一個或多個交互式窗口顯示圖形。canvas

須要注意的是:一個 Python 會話(session)中只能使用一次 plt.show(),所以一般都把它放在腳本的最後。多個 plt.show() 命令會致使難以預料的顯示異常,應該儘可能避免。數組

x = np.linspace(0, 10, 100) 
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x)) 
plt.show()

2. 在IPython shell中畫圖

在 IPython shell 中交互式地使用 Matplotlib 畫圖很是方便,在IPython 啓動 Matplotlib 模式就可使用它。爲了啓用這個模式,須要在啓動 ipython 後使用 %matplotlib 魔法命令:session

此後的任何 plt 命令都會自動打開一個圖形窗口,增長新的命令,圖形就會更新。dom

有一些變化(例如改變已經畫好的線條屬性)不會自動及時更新;對於這些變化,可使用plt.draw() 強制更新。在 IPython shell 中啓動 Matplotlib 模式以後,就不須要使用 plt.show() 了。ide

4.1.4 將圖形保存爲文件

使用 savefig() 命令能夠將圖形保存爲文件。svg

x = np.linspace(0, 10, 100) 
fig = plt.figure()
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))
fig.savefig('my_figure.png')

以上代碼將圖形以png格式保存在目錄下。函數

經過 canvas 對象的方法能夠查看系統支持的文件格式。工具

fig.canvas.get_supported_filetypes()
{'ps': 'Postscript',
 'eps': 'Encapsulated Postscript',
 'pdf': 'Portable Document Format',
 'pgf': 'PGF code for LaTeX',
 'png': 'Portable Network Graphics',
 'raw': 'Raw RGBA bitmap',
 'rgba': 'Raw RGBA bitmap',
 'svg': 'Scalable Vector Graphics',
 'svgz': 'Scalable Vector Graphics',
 'jpg': 'Joint Photographic Experts Group',
 'jpeg': 'Joint Photographic Experts Group',
 'tif': 'Tagged Image File Format',
 'tiff': 'Tagged Image File Format'}

4.2 兩種畫圖接口

Matplotlib 有一個容易讓人混淆的特性,就是它的兩種畫圖接口:一個是便捷的MATLAB 風格接口,另外一個是功能更強大的面向對象接口。

4.2.1 MATLAB風格接口

Matplotlib 最初做爲 MATLAB 用戶的 Python 替 代 品, 許 多 語 法 都 和 MATLAB 類 似。MATLAB 風格的工具位於 pyplot(plt)接口中。下面是典型的 Matlab 風格的代碼。

plt.figure() # 建立圖形
# 建立兩個子圖中的第一個,設置座標軸
plt.subplot(2, 1, 1) # (行、列、子圖編號) 
plt.plot(x, np.sin(x)) 
# 建立兩個子圖中的第二個,設置座標軸
plt.subplot(2, 1, 2) 
plt.plot(x, np.cos(x))

這種接口最重要的特性是有狀態的(stateful):它會持續跟蹤「當前的」圖形和座標軸,全部 plt 命令均可以應用。使用 plt.gcf()(獲取當前圖形)和 plt.gca()(獲取當前座標軸)能夠查看具體信息。

4.2.2 面向對象接口

# 先建立圖形網格
# ax是一個包含兩個Axes對象的數組
fig, ax = plt.subplots(2)
# 在每一個對象上調用plot()方法
ax[0].plot(x, np.sin(x))
ax[1].plot(x, np.cos(x))

4.3 簡易線形圖

plt.style.use('seaborn-whitegrid')
# 建立一個圖形 fig 和一個座標軸 ax
fig = plt.figure() 
ax = plt.axes()

在 Matplotlib 裏面,figure(plt.Figure 類的一個實例)能夠被當作是一個可以容納各類座標軸、圖形、文字和標籤的容器。axes(plt.Axes 類的一個實例)是一個帶有刻度和標籤的矩形,最終會包含全部可視化的圖形元素。
建立好座標軸以後,就能夠用 ax.plot 畫圖了。若是想在一張圖中建立多條線,能夠重複調用 plot 命令。

4.3.1 調整圖形:線條的顏色與風格

plt.plot() 函數能夠經過相應的參數設置顏色與風格。要修改顏色,就可使用 color 參數,它支持各類顏色值的字符串。

x= np.linspace(0, 10, 100)
plt.plot(x, np.sin(x - 0), color='blue') # 標準顏色名稱
plt.plot(x, np.sin(x - 1), color='g') # 縮寫顏色代碼(rgbcmyk)
plt.plot(x, np.sin(x - 2), color='0.75') # 範圍在0~1的灰度值
plt.plot(x, np.sin(x - 3), color='#FFDD44') # 十六進制(RRGGBB,00~FF)
plt.plot(x, np.sin(x - 4), color=(1.0,0.2,0.3)) # RGB元組,範圍在0~1 
plt.plot(x, np.sin(x - 5), color='chartreuse'); # HTML顏色名稱

若是不指定顏色,Matplotlib 就會爲多條線自動循環使用一組默認的顏色。
與之相似,你也能夠用 linestyle 調整線條的風格。

plt.plot(x, x + 0, linestyle='solid')
plt.plot(x, x + 1, linestyle='dashed')
plt.plot(x, x + 2, linestyle='dashdot')
plt.plot(x, x + 3, linestyle='dotted');
# 你能夠用下面的簡寫形式
plt.plot(x, x + 4, linestyle='-') # 實線
plt.plot(x, x + 5, linestyle='--') # 虛線
plt.plot(x, x + 6, linestyle='-.') # 點劃線
plt.plot(x, x + 7, linestyle=':'); # 實點線

一種更簡潔的方式是將 linestyle 和 color 編碼組合起來。

plt.plot(x, x + 0, '-g') # 綠色實線
plt.plot(x, x + 1, '--c') # 青色虛線
plt.plot(x, x + 2, '-.k') # 黑色點劃線
plt.plot(x, x + 3, ':r'); # 紅色實點線

4.3.2 調整圖形:座標軸上下限

調整座標軸上下限最基礎的方法是 plt.xlim() 和 plt.ylim()。

plt.plot(x, np.sin(x)) 
plt.xlim(-1, 11) 
plt.ylim(-1.5, 1.5);

還有一個方法是 plt.axis()(注意不要搞混 axes 和 axis)。經過傳入 [xmin, xmax, ymin, ymax] 對應的值。

plt.plot(x, np.sin(x)) 
plt.axis([-1, 11, -1.5, 1.5])
  • plt.axis('tight'):按照圖形的內容自動收緊座標軸,不留空白區域;
  • plt.axis('equal'):讓屏幕上顯示的圖形 x 軸單位長度與 y 軸單位長度相等。

4.3.3 設置圖形標籤

plt.plot(x, np.sin(x)) 
plt.title("A Sine Curve") 
plt.xlabel("x") 
plt.ylabel("sin(x)")

Matplotlib 內置了一個簡單快速的方法,能夠用來建立圖例,即plt.legend()。在 plt.plot 函數中用 label 參數爲每條線設置一個標籤更加簡單。

plt.plot(x, np.sin(x), '-g', label='sin(x)')
plt.plot(x, np.cos(x), ':b', label='cos(x)')
plt.legend()

一些 MATLAB 風格的方法和麪向對象方法的轉換以下所示:

  • plt.xlabel() → ax.set_xlabel()
  • plt.ylabel() → ax.set_ylabel()
  • plt.xlim() → ax.set_xlim()
  • plt.ylim() → ax.set_ylim()
  • plt.title() → ax.set_title()

在用面向對象接口畫圖時,不須要單獨調用這些函數,一般採用 ax.set() 方法一次性設置全部的屬性是更簡便的方法。

ax = plt.axes() 
ax.plot(x, np.sin(x)) 
ax.set(xlim=(0, 10), ylim=(-2, 2), \
       xlabel='x', ylabel='sin(x)', \
       title='A Simple Plot')

4.4 簡易散點圖

4.4.1 用plt.plot畫散點圖

x = np.linspace(0, 10, 30)
y = np.sin(x)
plt.plot(x, y, 'o', color='black')

部分圖形標記展現以下:

rng = np.random.RandomState(0) 
for marker in ['o', '.', ',', 'x', '+', 'v', '^', '<', '>', 's', 'd']: 
    plt.plot(rng.rand(5), rng.rand(5), marker, \
             label="marker='{0}'".format(marker)) 
    plt.legend(numpoints=1) 
    plt.xlim(0, 1.8)

plt.plot(x, y, '-or'); # 直線(-)、圓圈(o)、紅色(r)

這些標記還能夠與線條、顏色代碼組合起來,畫出一條鏈接散點的線。

plt.plot支持許多設置線條和散點屬性的參數,例如:

plt.plot(x, y, '-p', color='b', \
         markersize=15, linewidth=4, \
         markerfacecolor='w', \
         markeredgecolor='r', \
         markeredgewidth=2)

4.4.2 用plt.scatter畫散點圖

plt.scatter 與 plt.plot 的主要差異在於,前者在建立散點圖時具備更高的靈活性,能夠單獨控制每一個散點與數據匹配,也可讓每一個散點具備不一樣的屬性(大小、表面顏色、邊框顏色等)。

rng = np.random.RandomState(0) 
x = rng.randn(100) 
y = rng.randn(100) 
colors = rng.rand(100) 
sizes = 300 * rng.rand(100) 
plt.scatter(x, y, c=colors, s=sizes, \
            alpha=0.3, cmap='viridis') 
plt.colorbar() # 顯示顏色條

能夠用 Scikit-Learn 程序庫裏面的鳶尾花(iris)數據來演示。

from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data.T
plt.scatter(features[0], features[1], alpha=0.3, \
            s=100*features[3], c=iris.target, cmap='viridis') 
plt.xlabel(iris.feature_names[0])
plt.ylabel(iris.feature_names[1])

每一個點的座標值 (x, y) 分別表示花萼的長度和寬度,而點的大小表示花瓣的寬度,三種顏色對應三種不一樣類型的鳶尾花。


看到熟悉的iris忍不住和ggplot2對比一下,ggplot做圖以下:

library(ggplot2)
ggplot(data=iris,aes(Sepal.Length,Sepal.Width,
                     size=Petal.Width,
                     colour=Species,alpha=I(0.3)))+
  geom_point()+guides(colour=F,size=F)+
  labs(x="sepal length(cm)",y="sepal width(cm)")+
  theme_light()+theme(axis.title.x= element_text(size = 10),
                      axis.title.y= element_text(size = 10))


iris.feature_names
['sepal length (cm)',
 'sepal width (cm)',
 'petal length (cm)',
 'petal width (cm)']
iris.data.shape
(150, 4)

 iris.data是150行4列的數據矩陣,T表示轉置。

plt.plot 與 plt.scatter 在數據量較小的時候,效率上的差別不大。可是當數據變大到幾千個散點時,plt.plot 的效率將大大高於 plt.scatter。這是因爲 plt.scatter 會對每一個散點進行單獨的大小與顏色的渲染,所以渲染器會消耗更多的資源。

4.5 可視化異常處理

4.5.1 基本偏差線

x = np.linspace(0, 10, 50)
dy = 0.8
y = np.sin(x) + dy * np.random.randn(50)
plt.errorbar(x, y, yerr=dy, fmt='.k')

plt.errorbar(x, y, yerr=dy, fmt='o', color='black', \
             ecolor='lightgray', elinewidth=3, capsize=0)

4.5.2 連續偏差

Scikit-Learn 程序庫 API 裏面有一個簡單的高斯過程迴歸方法(Gaussian process regression,GPR),這是用一種很是靈活的非參數方程(nonparametric function)對帶有不肯定性的連續測量值進行擬合的方法。

能夠經過區域填充表示連續偏差。

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import ConstantKernel, RBF
# 定義模型和要畫的數據
kernel = ConstantKernel(constant_value=0.2, \
                        constant_value_bounds=(1e-4, 1e4)) * RBF(length_scale=0.5, \
                                              length_scale_bounds=(1e-4, 1e4))
gpr = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=2)
model = lambda x: x * np.sin(x)
xdata = np.array([1, 3, 5, 6, 8]).reshape(-1, 1)
ydata = model(xdata)
# 計算高斯過程擬合結果
gpr.fit(xdata, ydata)
xfit = np.linspace(0, 10, 1000).reshape(-1, 1)
mu, cov = gpr.predict(xfit, return_cov=True)
yfit = mu.ravel()
dyfit = 1.96 * np.sqrt(np.diag(cov))# 95%置信區間

# 將結果可視化
xfit = xfit.ravel()
plt.plot(xdata, ydata, 'or')
plt.plot(xfit, yfit, '-', color='gray')
plt.fill_between(xfit.ravel(), yfit - dyfit, yfit + dyfit, \
                 color='gray', alpha=0.2)
plt.xlim(0, 10)

從結果圖形中能夠很是直觀地看出高斯過程迴歸方法擬合的效果:在接近樣本點的區域,模型受到很強的約束,擬合偏差很是小,很是接近真實值;而在遠離樣本點的區域,模型不受約束,偏差不斷增大。

4.6 密度圖與等高線圖

用 plt.contour 畫等高線圖、用 plt.contourf 畫帶有填充色的等高線圖(filled contour plot)的色彩、用 plt.imshow 顯示圖形。

def f(x, y): 
    return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)
x = np.linspace(0, 5, 50) 
y = np.linspace(0, 5, 40) 
X, Y = np.meshgrid(x, y) 
Z = f(X, Y)
plt.contour(X, Y, Z, colors='black')

當圖形中只使用一種顏色時,默認使用虛線表示負數,使用實線表示正數。

plt.contour(X, Y, Z, 20, cmap='Set1')

在 IPython 裏使用 plt.cm.<TAB> 瀏覽 Matplotlib 中的配色方案。

使用 plt.imshow()能夠將二維數組渲染成漸變圖。

plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', \
           cmap='Set1')
plt.colorbar()
plt.axis(aspect='image')

還有一個可能會用到的方法,就是將等高線圖與彩色圖組合起來。首先須要用一幅背景色半透明的彩色圖,與另外一幅座標軸相同、帶數據標籤的等高線圖疊放在一塊兒。

contours = plt.contour(X, Y, Z, 3, colors='black')
plt.clabel(contours, inline=True, fontsize=8)
plt.imshow(Z, extent=[0, 5, 0, 5], origin='lower', \
           cmap='Set1', alpha=0.5) 
plt.colorbar()

相關文章
相關標籤/搜索