30000字 Matplotlib 實操干貨,38個案例帶你從入門到進階!
點擊上方“AI算法與圖像處理”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
Matplotlib 實操干貨,
38個案例帶你從入門到進階!
Matplotlib 是主流模塊之一??梢允褂?Matplotlib 以各種繪圖樣式來可視化數(shù)據(jù)。但是,Matplotlib 無法顯示動態(tài)圖。如果要創(chuàng)建一個巨大的動態(tài)圖,則可以從 plotly 中使用 Dash 。
本文將介紹如何使用 Matplotlib 以各種方式可視化數(shù)據(jù)。完整的文章可能有 90 個示例,可以從不同的角度創(chuàng)建繪圖。這不是使用 Matplotlib 進行數(shù)據(jù)可視化的最完整的教程,但是我相信本文內(nèi)容可以滿足許多人的需求,并可以應用到許多領域。
如前所述,本文將創(chuàng)建 90 個不同的繪圖示例。這些示例分布在 11 種不同的樣式圖中:散點圖,折線圖,一維直方圖,二維直方圖,邊際圖,條形圖,箱形圖,小提琴圖,餅圖,極坐標圖,地理投影,3D圖和輪廓圖。可以通過 圖1 大致了解本文的內(nèi)容。
本文將專注于創(chuàng)建和定制各種圖表。因此,文章中假設讀者已經(jīng)了解 Matplotlib 的一些基礎知識,例如,在 Matplotlib 中創(chuàng)建多個子圖和自定義顏色圖。
在開始撰寫本文時,本來打算只寫一篇文章。但是,我認為由于閱讀時間的緣故,需要將其分為幾部分。如果我將所有內(nèi)容寫成一篇文章,則將花費很多時間。因此,我將完整的內(nèi)容分為 2 或 3 部分。
本文是第一部分,共有 38個 案例,讓我們開始吧。
Matplotlib 介紹
要安裝 Matplotlib,可以使用以下代碼通過 pip 安裝它:
pip install matplotlib
或者通過 conda 來安裝:
conda install -c anaconda matplotlib
本文中,安裝了 Matplotlib 3.3.2 版本??梢酝ㄟ^下面的代碼檢查所安裝的版本號:
pip show matplotlib
如果要在 Jupyter Notebook(以下稱為 Jupyter)中進行檢查,則可以通過下面的代碼來進行檢查,如圖2所示。
如果你想更新 Matplotlib 的版本,可以使用下面的代碼:
pip install matplotlib --upgrade
在繼續(xù)進行第一部分之前,需要告知下,我已經(jīng)自定義了 Matplotlib 繪圖樣式,例如使用 LaTeX 字體作為默認樣式,更改字體大小和字體,更改 xtick 和 ytick 方向和大小,以及在 x 軸和 y 軸。要將 LaTeX 字體用作 Matplotlib 中的默認字體,可以使用下面的代碼:
plt.rcParams['text.usetex'] = True
如果遇到一些錯誤,則需要閱讀下面文章中的內(nèi)容。我已經(jīng)解釋了在 Matplotlib 中處理 LaTeX 字體的詳細過程。
https://towardsdatascience.com/5-powerful-tricks-to-visualize-your-data-with-matplotlib-16bc33747e05
要自定義其他參數(shù)(字體大小,字體系列和刻度參數(shù)),只需在代碼開頭編寫以下代碼:
plt.rcParams['font.size'] = 15
plt.rcParams['font.family'] = "serif"tdir = 'in'
major = 5.0
minor = 3.0
plt.rcParams['xtick.direction'] = tdir
plt.rcParams['ytick.direction'] = tdirplt.rcParams['xtick.major.size'] = major
plt.rcParams['xtick.minor.size'] = minor
plt.rcParams['ytick.major.size'] = major
plt.rcParams['ytick.minor.size'] = minor
如果需要更詳細地了解,可以訪問下面的內(nèi)容:
https://towardsdatascience.com/create-professional-plots-using-matplotlib-63a6863b7363
01. 散點圖(Scatter plot)
在本部分,有八個散點圖的示例。在創(chuàng)建散點圖之前,需要使用下面的代碼生成模擬數(shù)據(jù):
import numpy as np
import matplotlib.pyplot as plt
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
變量 x 是從 0 到 10 的 50 個數(shù)據(jù)的數(shù)組。變量 y 是 sin(x) 和 cos(x) 的平方之和??梢允褂靡韵麓a以散點圖的形式可視化 x 軸上的變量 x 和 y 軸上的變量 y :
plt.figure()
plt.scatter(x, y)
上面的內(nèi)容很簡單,結(jié)果如圖3所示:
為了使其更美觀,可以減少每個數(shù)據(jù)的大小并給標簽添加下面的代碼:
plt.scatter(x, y, s = 15, label = r'$y = sin^2(x) + cos(x)$')
要更改顏色,需要在代碼中添加 color 參數(shù):
color = 'r' # r means red
如果要使軸比例尺相同,可以使用下面的代碼:
plt.axis('equal')
要為 x 軸和 y 軸創(chuàng)建軸標簽,可以添加以下代碼:
plt.xlabel(r'$x$ (rad)')
plt.ylabel(r'$y$')
要顯示圖例,可以使用下面的代碼:
plt.legend()
要保存圖形,可以使用以下代碼:
plt.savefig('scatter2.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
完整的代碼如下:
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
plt.figure()
plt.scatter(x, y, s = 15, label = r'$ y = sin^2(x) + cos(x)$', color = 'r')
plt.axis('equal')
plt.legend()
plt.xlabel(r'$x$ (rad)')
plt.ylabel(r'$y$')
plt.savefig('scatter2.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
創(chuàng)建的散點圖如 圖4 所示:
上面可以看到軸內(nèi)部的 x 軸和 y 軸的刻度方向,并且使用的字體為 LaTeX 格式。如果要更改圖形尺寸,可以在 plt.figure() 中添加圖形尺寸參數(shù)
plt.figure(figsize=(7, 4.5))
更改標記樣式
要更改標記樣式,例如,要從點更改為十字,可以在 plt.scatter 中添加此參數(shù):
marker = 'x'
圖5 是更改為十字后的結(jié)果:
Matplotlib 中有各種各樣的樣式,可以通過下面的鏈接來進行了解:
https://matplotlib.org/api/markers_api.html
如果你已閱讀以上文檔,則可以意識到可以將字母用作標記樣式。下面將展示將字母用作標記的示例,如 圖6 所示:
為了生成 圖6,這里為 x 軸和 y 軸的參數(shù)創(chuàng)建了一個不同的函數(shù)。以下是生成它的代碼:
np.random.seed(100)
N = 50
randx = np.random.random(N) * 100
randy = np.random.random(N) * 100
為了可視化變量 randx 和 randy ,可以運行以下代碼:
plt.figure(figsize=(7, 6))
plt.scatter(randx, randy, marker=r'$\beta$', s = 150, color = 'darkorange')
plt.axis('equal')
plt.xlabel('randx')
plt.ylabel('randy')
plt.tight_layout()
這里使用希臘符號 beta 作為標記樣式。也可以使用其他字母來更改它,例如 a,B,C,d 或 ** 1、2、3** 等。
自定義每個數(shù)據(jù)的大小
這里將展示如何為每個數(shù)據(jù)創(chuàng)建大小不同的散點圖,如 圖7 所示。
為了創(chuàng)建它,使用以下代碼為變量 randx 和 randy 生成了一個隨機數(shù)據(jù),從 0 到 100
np.random.seed(100)
N = 30
randx = np.random.random(N) * 100
randy = np.random.random(N) * 100
之后,使用下面的代碼為 50 到 200 之間的每個數(shù)據(jù)生成一個隨機整數(shù)。
size = np.random.randint(50, 200, size=N)
進行可視化,只需添加下面的參數(shù):
plt.scatter(randx, randy, s = size, color = 'darkorange')
創(chuàng)建 圖7 時需要在 x 軸和 y 軸上插入次刻度。要插入它,需要使用以下代碼導入子模塊 MultipleLocator :
from matplotlib.ticker import MultipleLocator
之后,可以添加以下代碼,以插入輔助軸:
ax = plt.gca()ax.xaxis.set_minor_locator(MultipleLocator(10))
ax.yaxis.set_minor_locator(MultipleLocator(10))
下面是生成 圖7 的完整代碼:
np.random.seed(100)
N = 30
plt.figure(figsize=(7, 6))
randx = np.random.random(N) * 100
randy = np.random.random(N) * 100
size = np.random.randint(50, 200, size=N)
plt.scatter(randx, randy, s = size, color = 'darkorange')
plt.axis('equal')
ax = plt.gca()
ax.xaxis.set_minor_locator(MultipleLocator(10))
ax.yaxis.set_minor_locator(MultipleLocator(10))
plt.xlabel('randx')
plt.ylabel('randy')
plt.savefig('scatter5.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
以顏色編碼的散點圖
可以使用顏色圖更改顏色,這意味著具有不同大小的數(shù)據(jù)將以不同的顏色進行顏色編碼。可以像下面這樣在 plt.scatter() 中添加顏色參數(shù):
c = size
要嵌入顏色條,可以使用以下代碼:
plt.colorbar()
得到的結(jié)果如 圖8 所示:
以下是創(chuàng)建 圖8 完整的代碼:
np.random.seed(100)
N = 30
randx = np.random.random(N) * 100
randy = np.random.random(N) * 100
ranking = np.random.random(N) * 200
size = np.random.randint(50, 200, size=N)
plt.figure(figsize=(7, 5))
plt.scatter(randx, randy, s = size, c = size, alpha = .8)
plt.axis('equal')
ax = plt.gca()
ax.xaxis.set_minor_locator(MultipleLocator(10))
ax.yaxis.set_minor_locator(MultipleLocator(10))
plt.xlabel('randx')
plt.ylabel('randy')
plt.colorbar()
plt.savefig('scatter6.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
自定義顏色圖
可以使用以下參數(shù)更改顏色圖:
cmap = 'inferno'
Matplotlib 官方文檔對顏色圖進行了詳細的講解,可以通過下面鏈接來訪問:
https://matplotlib.org/3.3.2/tutorials/colors/colormaps.html
在本文中,通過組合藍色和橙色的顏色圖創(chuàng)建了自己的顏色圖,如 圖9 所示:
使用下面的代碼,可以將兩種顏色結(jié)合起來:
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
top = cm.get_cmap('Oranges_r', 128)
bottom = cm.get_cmap('Blues', 128)
newcolors = np.vstack((top(np.linspace(0, 1, 128)),
bottom(np.linspace(0, 1, 128))))
orange_blue = ListedColormap(newcolors, name='OrangeBlue')
我創(chuàng)建了自己的顏色圖,名為 orange_blue 。要了解如何在 Matplotlib 中創(chuàng)建和自定義自己的顏色圖,可以訪問以下鏈接:
https://towardsdatascience.com/creating-colormaps-in-matplotlib-4d4de78a04b8
要應用它,只需更改顏色參數(shù) c = orange_blue ,可以在 圖11 中檢查結(jié)果:
以下是創(chuàng)建 圖11 的完整代碼:
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
top = cm.get_cmap('Oranges_r', 128)
bottom = cm.get_cmap('Blues', 128)
newcolors = np.vstack((top(np.linspace(0, 1, 128)),
bottom(np.linspace(0, 1, 128))))
orange_blue = ListedColormap(newcolors, name='OrangeBlue')
np.random.seed(100)
N = 30
randx = np.random.random(N) * 100
randy = np.random.random(N) * 100
size = np.random.randint(50, 200, size=N)
plt.figure(figsize=(7, 5))
plt.scatter(randx, randy, s = size, c = size, alpha = .8, cmap = orange_blue)
plt.axis('equal')
ax = plt.gca()
ax.xaxis.set_minor_locator(MultipleLocator(10))
ax.yaxis.set_minor_locator(MultipleLocator(10))
plt.xlabel('randx')
plt.ylabel('randy')
plt.colorbar(label = 'circle size')
plt.savefig('scatter7.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
02. 線圖(Line plot)
為了在 Matplotlib 中繪制線圖,將使用以下代碼生成模擬數(shù)據(jù):
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
要以線圖的形式可視化變量 x 和 y ,需要使用以下代碼:
plt.plot(x, y)
上面的代碼將生成一個圖形,如 圖12 所示:
自定義線條的樣式
可以使用下面的參數(shù)在 Matplotlib 中更改線條圖的線條樣式:
linestyle = '-'
上面的參數(shù)應在 plt.plot() 中插入。在本文中將展示四種不同的線條樣式。它們是
['-', '--', '-.', ':']
為了自動生成它,使用循環(huán)將使其變得簡單,以下是完整的代碼:
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
rows = 2
columns = 2
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
linestyles = ['-', '--', '-.', ':']
plt.figure(figsize=(15, 10))
for i in range(len(linestyles)):
plt.subplot(grid[i])
plt.plot(x, y, linestyle = linestyles[i], label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.xlabel('$x$ (rad)')
plt.legend()
plt.annotate("linestyle '" + str(linestyles[i]) + "'", xy = (0.5, -2.5), va = 'center', ha = 'left')
plt.savefig('line2.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
這里將在一張圖中分配 4 種不同的線型,這意味著需要在一個圖中創(chuàng)建 4 個軸。在 Matplotlib 中,可以通過使用 GridSpec() ,subplot() 和 add_subplot() 自定義子圖來生成它。在本文中,使用 GridSpec() ,創(chuàng)建了 4 個軸( 2 行 2 列),寬度和高度間距等于 0.25。
正如在文章開始時提到的,本文將只專注于自定義圖。如果在 Matplotlib 中自定義子圖時需要更多說明,則可以訪問下面的鏈接:
https://towardsdatascience.com/customizing-multiple-subplots-in-matplotlib-a3e1c2e099bc
上面代碼運行后的結(jié)果如 圖13 所示:
該代碼將簡單地生成 4 種不同的線型,并為每種線型添加標簽和注釋。Matplotlib 提供了許多可以使用的線型,可以通過下面鏈接選擇自己喜歡的線條樣式:
https://matplotlib.org/2.1.2/api/_as_gen/matplotlib.pyplot.plot.html
自定義線條寬度
自定義線條寬度,可以使用下面的代碼:
lw = 2.0
四種不同寬度的線條圖,如 圖14 所示:
創(chuàng)建 圖14 的完整代碼如下:
N = 50
rows = 2
columns = 2
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
linewidth = [2, 3, 4, 5]
plt.figure(figsize=(15, 10))
for i in range(len(linestyles)):
plt.subplot(grid[i])
plt.plot(x, y, linestyle = '-.', lw = linewidth[i], label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.xlabel('$x$ (rad)')
plt.legend()
plt.annotate("linewidth " + str(linewidth[i]), xy = (0.5, -2.5), va = 'center', ha = 'left')
plt.savefig('line3.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
創(chuàng)建間隔標記
這里將創(chuàng)建間隔標記(mark every)。為了理解它,將首先顯示結(jié)果,如 圖15 所示:
在 圖15 中,為每 5 個數(shù)據(jù)創(chuàng)建一個圓圈標記??梢允褂靡韵聟?shù)創(chuàng)建:
'o' # shape for each 5 data
markevery = 5 # mark every
ms = 7 # size of the circle in mark every
以下是完整的代碼:
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
plt.figure(figsize=(7, 4.5))
plt.plot(x, y, 'o', ls = '-.', lw = 2, ms = 7, markevery = 5, label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.xlabel('$x$ (rad)')
plt.legend()
plt.annotate("markevery: 5", xy = (0.5, -2.5), va = 'center', ha = 'left')
plt.savefig('line4.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
這里需要將參數(shù) "o" 放在第三個參數(shù)位置上。
更改線條顏色
更改線條顏色,可以使用以下代碼:
color = 'royalblue'
下面將展示如何使用循環(huán)生成 4 種不同的顏色和 4 種不同的標記,如 圖16 所示:
創(chuàng)建 圖16 的代碼如下:
N = 50
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
rows = 2
columns = 2
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
mark = [2, 5, 10, 12]
color = ['#00429d', '#627c94', '#f4777f', '#93003a']
plt.figure(figsize=(15, 10))
for i in range(len(linestyles)):
plt.subplot(grid[i])
plt.plot(x, y, 'o', ls='-.', lw = 2, ms = 8, markevery=mark[i], color = color[i], label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.annotate("markevery: " + str(mark[i]), xy = (0.5, -2.5), va = 'center', ha = 'left')
plt.xlabel('$x$ (rad)')
plt.legend()
plt.savefig('line5.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
線條圖中添加誤差
為了演示折線圖中的誤差線,需要使用以下代碼生成誤差:
np.random.seed(100)
noise_x = np.random.random(N) * .2 + .1
noise_y = np.random.random(N) * .7 + .4
該代碼將為 noise_x 生成從 0.1 到 0.3 的隨機數(shù),為 noise_y 生成從 0.3 到 0.7 的隨機數(shù)。要為 y 軸插入誤差線,可以使用以下代碼:
plt.errorbar(x, y, yerr = noise_y)
包含誤差的線條圖,如 圖17 所示:
創(chuàng)建 圖17 的完整代碼如下:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise_x = np.random.random(N) * .2 + .1
noise_y = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.errorbar(x, y, yerr = noise_y, xerr = noise_x, label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.legend()
plt.xlabel('$x$ (rad)')
plt.savefig('line7.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
在 x 軸添加誤差,可以使用以下參數(shù):
xerr = noise_x
可以看到在 圖18 的 x 和 y 軸上插入誤差線的示例:
創(chuàng)建 圖18 的完整代碼如下:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise_x = np.random.random(N) * .2 + .1
noise_y = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.errorbar(x, y, yerr = noise_y, xerr = noise_x, label = r'$ y = sin^2(x) + cos(x)$')
plt.axis('equal')
plt.legend()
plt.xlabel('$x$ (rad)')
plt.savefig('line7.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
如果只想顯示數(shù)據(jù)而不顯示線圖,而僅顯示誤差線,則可以使用以下參數(shù):
fmt = 'o' # shape of the data point
color = 'r' # color of the data point
ecolor ='k' # color of the error bar
完整代碼如下:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise_x = np.random.random(N) * .2 + .1
noise_y = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.errorbar(x, y, xerr = noise_x, yerr = noise_y, label = r'$ y = sin^2(x) + cos(x)$', color = 'r', fmt = 'o', ecolor='k', )
plt.axis('equal')
plt.legend()
plt.xlabel('$x$ (rad)')
plt.savefig('line8.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
效果如 圖19 所示:
填充誤差區(qū)域
如需要填充誤差范圍區(qū)域,可以使用以下代碼:
plt.fill_between(x, y + noise, y - noise, alpha = .5)
fill_between 參數(shù)是 x 軸的數(shù)據(jù),填充區(qū)域的上限和下限。在上面的代碼中,用 y + noise 和 y-noise 表示。此外,還需要降低填充區(qū)域的透明度。以下是完整的代碼:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.plot(x, y, ls='-', label = r'$ y = sin^2(x) + cos(x)$')
plt.fill_between(x, y + noise, y - noise, alpha = .5)
plt.axis('equal')
plt.legend()
plt.xlabel('$x$ (rad)')
plt.savefig('line9.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
上述代碼運行后,結(jié)果如 圖20 所示:
插入水平線和垂直線
可以使用以下代碼插入水平線和垂直線:
plt.hlines(0, xmin = 0, xmax = 10)
plt.vlines(2, ymin = -3, ymax = 3)
需要在第一個參數(shù)中定義水平線,包括水平線的起點和終點。對于垂直線,它具有類似的參數(shù)。
圖21 是添加了水平線和垂直線的示例:
創(chuàng)建 圖21 的完整代碼如下:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.plot(x, y, ls = '-', label = r'$ y = sin^2(x) + cos(x)$', color = 'darkgreen')
plt.fill_between(x, y + noise, y - noise, color = 'darkgreen', alpha = .5)
plt.axis('equal')
plt.hlines(0, xmin = 0, xmax = 10, ls = '--', color = 'royalblue', label = 'hlines')
plt.vlines(2, ymin = -3, ymax = 3, ls = '--', color = 'orange', label = 'vlines')
plt.legend(bbox_to_anchor=(1.55, 1.04)) # position of the legend
plt.xlabel('$x$ (rad)')
plt.savefig('line10.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
垂直填充
下面將在兩條垂直線之間繪制一個填充區(qū)域,如 圖22 所示:
創(chuàng)建 圖22 的完整代碼如下:
N = 25
x = np.linspace(0., 10., N)
y = np.sin(x)**2 + np.cos(x)
np.random.seed(100)
noise = np.random.random(N) * .7 + .4
plt.figure(figsize=(7, 4.5))
plt.plot(x, y, ls='-', label = r'$ y = sin^2(x) + cos(x)$', color = 'darkgreen')
plt.fill_between(x, y + noise, y - noise, color = 'darkgreen', alpha = .5)
plt.axis('equal')
plt.fill_between((2,4), -3.2, 3.2, facecolor='orange', alpha = 0.4)
plt.xlim(0, 10)
plt.ylim(-3, 3)
plt.legend()
plt.xlabel('$x$ (rad)')
plt.savefig('line11.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
03. 直方圖(Histogram)
下面將說明如何在 1D 和 2D 中制作直方圖。首先,將介紹一維直方圖。在可視化一維直方圖之前,將使用以下代碼制作一個模擬數(shù)據(jù),即正態(tài)分布隨機數(shù)。
N = 1000
np.random.seed(10021)
x = np.random.randn(N) * 2 + 15
默認情況下,Numpy 將生成一個正態(tài)分布隨機數(shù),其均值/中位數(shù)(mu)等于 0 ,方差(sigma)等于 1 。在上面的代碼中,將 mu 更改為15,將 sigma 更改為 2 。要在一維直方圖中可視化變量 x ,可以使用以下代碼:
plt.hist(x)
結(jié)果如 圖23 所示:
在 Matplotlib 中, 一維直方圖中 bins 的默認值為 10, 如果要更改 bins 的默認值,可以修改下面的參數(shù):
bins = 40
將 bins 設置為 40 后,結(jié)果如 圖24 所示:
以下是創(chuàng)建 圖24 的完整代碼:
N = 1000
np.random.seed(10021)
x = np.random.randn(N) * 2 + 15
plt.figure(figsize=(9, 6))
plt.hist(x, bins = 40, label = r'$\mu = 15, \sigma = 2$')
plt.legend()
還可以使用以下參數(shù)限制直方圖的范圍:
range = (12, 18)
該參數(shù)將使直方圖僅顯示 12 到 18 之間的數(shù)據(jù),如 圖25 所示:
創(chuàng)建 圖25 的完整代碼如下:
N = 1000
np.random.seed(10021)
x = np.random.randn(N) * 2 + 15
plt.figure(figsize=(9, 6))
plt.hist(x, bins = 40, range = (12, 18), color = 'darkorange', label = r'$\mu = 15, \sigma = 2$')
plt.legend()
plt.savefig('hist3.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
這里還使用 color 參數(shù)更改直方圖的顏色。
水平直方圖
可以創(chuàng)建一個水平直方圖,如 圖26 所示:
使用以下參數(shù)來創(chuàng)建水平直方圖:
orientation = 'horizontal'
創(chuàng)建 圖25 的完整代碼如下:
N = 1000
np.random.seed(10021)
x = np.random.randn(N) * 2 + 15
plt.figure(figsize=(9, 6))
plt.hist(x, bins = 25, range = (12, 18), color = 'royalblue', orientation='horizontal', label = r'$\mu = 15, \sigma = 2$')
plt.legend()
plt.savefig('hist4.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
如果要顯示每個直方圖的邊框,可以使用下面的參數(shù)。
edgecolor = 'k'
將直方圖邊框設為黑色,如 圖26 所示:
創(chuàng)建 圖26 的完整代碼如下:
N = 1000
np.random.seed(10021)
x = np.random.randn(N) * 2 + 15
plt.figure(figsize=(9, 6))
plt.hist(x, bins = 25, range = (12, 18), color = 'royalblue', orientation='horizontal', edgecolor='k', label = r'$\mu = 15, \sigma = 2$')
plt.legend()
plt.savefig('hist5.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
重疊的直方圖
可以在一個圖中顯示許多個直方圖,如 圖27 所示:
在 圖27 中,生成了三個正態(tài)分布,分別具有不同的 mu 和 sigma ,代碼如下:
N = 1000
mu1 = 5
mu2 = 10
mu3 = 15
sigma1 = 5
sigma2 = 3
sigma3 = 2
x1 = np.random.randn(N) * sigma1 + mu1
x2 = np.random.randn(N) * sigma2 + mu2
x3 = np.random.randn(N) * sigma3 + mu3
plt.figure(figsize=(9, 6))
plt.hist(x1, bins = 30, color = 'royalblue', label = r'$\mu = $ ' + str(mu1) + ', $\sigma = $ ' + str(sigma1))
plt.hist(x2, bins = 30, color = 'tomato', label = r'$\mu = $ ' + str(mu2) + ', $\sigma = $ ' + str(sigma2))
plt.hist(x3, bins = 30, color = 'gray', label = r'$\mu = $ ' + str(mu3) + ', $\sigma = $ ' + str(sigma3))
plt.legend()
plt.savefig('hist6.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
可以通過更改直方圖的透明度使其更美觀,如 圖28 所示:
創(chuàng)建 圖28 的完整代碼如下,與之前的代碼的不同之處,在于增加了 alpha 參數(shù):
N = 1000
mu1 = 5
mu2 = 10
mu3 = 15
sigma1 = 5
sigma2 = 3
sigma3 = 2
x1 = np.random.randn(N) * sigma1 + mu1
x2 = np.random.randn(N) * sigma2 + mu2
x3 = np.random.randn(N) * sigma3 + mu3
plt.figure(figsize=(9, 6))
plt.hist(x1, bins = 30, color = 'royalblue', label = r'$\mu = $ ' + str(mu1) + ', $\sigma = $ ' + str(sigma1), alpha = .7)
plt.hist(x2, bins = 30, color = 'tomato', label = r'$\mu = $ ' + str(mu2) + ', $\sigma = $ ' + str(sigma2), alpha = .7)
plt.hist(x3, bins = 30, color = 'gray', label = r'$\mu = $ ' + str(mu3) + ', $\sigma = $ ' + str(sigma3), alpha = .7)
plt.legend()
plt.savefig('hist7.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
還可以使用循環(huán)生成 圖28,如代碼所示:
N = 1000
mu1 = 5
mu2 = 10
mu3 = 15
sigma1 = 5
sigma2 = 3
sigma3 = 2
x1 = np.random.randn(N) * sigma1 + mu1
x2 = np.random.randn(N) * sigma2 + mu2
x3 = np.random.randn(N) * sigma3 + mu3
mu = np.array([mu1, mu2, mu3])
sigma = np.array([sigma1, sigma2, sigma3])
x = np.array([x1, x2, x3])
colors = ['royalblue', 'tomato', 'gray']
plt.figure(figsize=(9, 6))
for i in range(len(x)):
plt.hist(x[i], bins = 30, color = colors[i],
label = r'$\mu = $ ' + str(mu[i]) +
', $\sigma = $ ' + str(sigma[i]), alpha = .7)
plt.legend()
看完上面的代碼后,也許你想試試,在單個圖形中創(chuàng)建很多直方圖(超過 3 個)。下面這個是在單個圖形中創(chuàng)建和可視化 10 個直方圖的代碼:
N_func = 10
N_data = 1000
np.random.seed(1000)
mu = np.random.randint(low = -5, high = 5, size = N_func)
sigma = np.random.randint(low = 1, high = 5, size = N_func)
x = []
for i in range(len(mu)):
xi = np.random.randn(N_data) * sigma[i] + mu[i]
x.append(xi)
colors = ['#00429d', '#7f40a2', '#a653a1', '#c76a9f', '#e4849c', '#d0e848',
'#b6cf54', '#a9b356', '#b2914b', '#ff0001']
plt.figure(figsize=(9, 6))
for i in range(len(mu)):
plt.hist(x[i], bins = 30, color = colors[i], label = r'$\mu = $ ' + str(mu[i]) + ', $\sigma = $ ' + str(sigma[i]), alpha = .7)
plt.legend(bbox_to_anchor=(1.33, 1.03))
運行代碼后,結(jié)果如 圖29 所示:
顏色的選擇參考以下鏈接:https://gka.github.io/palettes/
生成調(diào)色板的詳細過程可以參考以下內(nèi)容:https://towardsdatascience.com/create-professional-plots-using-matplotlib-63a6863b7363
二維直方圖
可以使用 Matplotlib 生成 2D 直方圖,如 圖30 所示。
要創(chuàng)建 圖30,需要使用以下代碼生成 2 個正態(tài)分布。
N = 1_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
要在 2D 直方圖中可視化變量 x 和 y ,可以使用以下代碼:
plt.hist2d(x, y)
與一維直方圖一樣,Matplotlib 中 bins 的默認值為 10 。要對其進行更改,可以應用與一維直方圖中相同的參數(shù),如下面的代碼所示:
bins = (25, 25)
可以在 圖31 中看到二維直方圖的修改效果:
還可以使用下面的參數(shù)更改二維直方圖的顏色圖:
cmap = orange_blue
我想將 Viridis 的顏色圖( Matplotlib 中的默認顏色圖)更改為自己的名為 orange_blue 的顏色圖。我已在上文中說明了如何創(chuàng)建自己的顏色圖。
以下是修改了顏色圖后的完整代碼:
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
top = cm.get_cmap('Oranges_r', 128)
bottom = cm.get_cmap('Blues', 128)
newcolors = np.vstack((top(np.linspace(0, 1, 128)),
bottom(np.linspace(0, 1, 128))))
orange_blue = ListedColormap(newcolors, name='OrangeBlue')
N = 10_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
plt.figure(figsize=(8.5, 7))
plt.hist2d(x, y, bins=(75, 75), cmap = orange_blue)
cb = plt.colorbar()
cb.set_label('counts each bin', labelpad = 10)
plt.savefig('hist12.png', dpi = 300, bbox_inches = 'tight', facecolor='w')
運行上述代碼,結(jié)果如 圖32 所示:
同樣的,可以通過設置參數(shù)應用于 plt.hist2d() 來限制每個計數(shù)的范圍(更改顏色條的限制)。
cmin = 5, cmax = 25
以下是完整的代碼:
N = 10_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
plt.figure(figsize=(8.5, 7))
plt.hist2d(x, y, bins=(75, 75), cmap = 'jet', cmin = 5, cmax = 25)
cb = plt.colorbar()
cb.set_label('counts each bin', labelpad = 10)
這里使用 “jet” 顏色圖,顏色條的下限等于 5 ,上限為 25 。結(jié)果如 圖33 所示:
還可以嘗試使用以下代碼將生成的隨機數(shù)計數(shù)從 10000 更改為 100000 。
N = 100_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
plt.figure(figsize=(8.5, 7))
plt.hist2d(x, y, bins=(75, 75), cmap = 'Spectral')
cb = plt.colorbar()
cb.set_label('counts each bin', labelpad = 10)
結(jié)果如 圖34 所示:
圖34 在 0 處達到峰值,在 -1 到 1 處分布,因為沒有改變 mu 和 sigma 的值。
邊際圖(Marginal plot)
「Python數(shù)據(jù)之道」注:邊際圖(Marginal plot),在有些地方也成為 聯(lián)合分布圖 (Joint plot)。
這里將介紹如何創(chuàng)建邊際分布,如 圖35 所示:
圖35 由散點圖和 2 個直方圖構建。要創(chuàng)建它,需要了解如何在單個圖形中自定義子圖或軸。圖35 由 25 個軸( 5 列 5 行)構成。詳細信息如 圖36 所示。
可以使用以下代碼創(chuàng)建 圖36 :
你可能需要閱讀下面的內(nèi)容,才能更好的理解:https://towardsdatascience.com/customizing-multiple-subplots-in-matplotlib-a3e1c2e099bc
rows = 5
columns = 5
grid = plt.GridSpec(rows, columns, wspace = .4, hspace = .4)
plt.figure(figsize=(10, 10))
for i in range(rows * columns):
plt.subplot(grid[i])
plt.annotate('grid '+ str(i), xy = (.5, .5), ha = 'center',
va = 'center')
for i in range(rows):
exec (f"plt.subplot(grid[{i}, 0])")
plt.ylabel('rows ' + str(i), labelpad = 15)
for i in range(columns):
exec (f"plt.subplot(grid[-1, {i}])")
plt.xlabel('column ' + str(i), labelpad = 15)
圖35 顯示了 圖36 的轉(zhuǎn)換。這里將 圖36 中的一些網(wǎng)格合并為僅 3 個較大的網(wǎng)格。第一個網(wǎng)格將網(wǎng)格0 合并到網(wǎng)格3(行1 ,列0 到列 )。我將用直方圖填充第一個網(wǎng)格。第二個網(wǎng)格合并從第 1 行到第 4 行以及從第 0 列到第 3 列的 16 個網(wǎng)格。最后一個網(wǎng)格是通過合并網(wǎng)格9、14、19 和 24(行1、2、3、4和列4)構建的。
要創(chuàng)建第一個網(wǎng)格,可以使用以下代碼:
rows = 5
columns = 5
grid = plt.GridSpec(rows, columns, wspace = .4, hspace = .4)
plt.figure(figsize=(10, 10))
plt.subplot(grid[0, 0:-1])
之后,添加以下代碼以插入一維直方圖:
plt.hist(x, bins = 30, color = 'royalblue', alpha = .7)
要創(chuàng)建第二個網(wǎng)格,可以將以下代碼添加到上面的代碼中:
plt.subplot(grid[1:rows+1, 0:-1])
添加下面的代碼以在第二個網(wǎng)格中生成散點圖:
plt.scatter(x, y, color = 'royalblue', s = 10)
plt.axis('equal')
以下是生成第三個網(wǎng)格及其直方圖的代碼,需要將下面的代碼插入第一個網(wǎng)格代碼中:
plt.subplot(grid[1:rows+1, -1])
plt.hist(y, bins = 30, orientation='horizontal',
color = 'royalblue', alpha = .7)
合并上面的代碼,完整的代碼如下:
N = 10_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
rows = 5
columns = 5
grid = plt.GridSpec(rows, columns, wspace = .4, hspace = .4)
plt.figure(figsize=(10, 10))
plt.subplot(grid[0, 0:-1])
plt.hist(x, bins = 30, color = 'royalblue', alpha = .7)
plt.subplot(grid[1:rows+1, 0:-1])
plt.scatter(x, y, color = 'royalblue', s = 10)
plt.axis('equal')
plt.subplot(grid[1:rows+1, -1])
plt.hist(y, bins = 30, orientation='horizontal', color = 'royalblue', alpha = .7)
接下來,將使用二維直方圖更改第二個網(wǎng)格中的散點圖,如 圖37 所示:
創(chuàng)建 圖37 的完整代碼如下:
N = 10_000
np.random.seed(100)
x = np.random.randn(N)
y = np.random.randn(N)
rows = 5
columns = 5
grid = plt.GridSpec(rows, columns, wspace = .4, hspace = .4)
plt.figure(figsize=(10, 10))
plt.subplot(grid[0, 0:-1])
plt.hist(x, bins = 40, color = 'royalblue', alpha = .3)
plt.annotate('Normal 1', xy = (2, 500), va = 'center', ha = 'left')
plt.subplot(grid[1:rows+1, 0:-1])
plt.hist2d(x, y, cmap = 'Blues', bins = (40, 40))
plt.axis('equal')
plt.subplot(grid[1:rows+1, -1])
plt.hist(y, bins = 40, orientation='horizontal', color = 'royalblue', alpha = .3)
plt.annotate('Normal 2', xy = (500, 2), va = 'bottom', ha = 'center', rotation = -90)
「Python數(shù)據(jù)之道」注:使用 Matplotlib 來創(chuàng)建邊際圖,相對來說比較繁瑣些,建議可以使用 seaborn 來創(chuàng)建 聯(lián)合分布圖 (Joint plot),其效果是差不多的。
可以參考下面文章:
04. 條形圖(Bar chart)
如果想用條形圖可視化數(shù)據(jù),在 Matplotlib 中創(chuàng)建條形圖之前,先創(chuàng)建要顯示的模擬數(shù)據(jù)。比如在數(shù)學考試成績中創(chuàng)建六個人的數(shù)據(jù),要創(chuàng)建它,使用以下代碼。
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
np.random.seed(100)
N = len(name)
math = np.random.randint(60, 100, N)
生成的數(shù)學考試成績從 60 到 100 ,代碼如下:
plt.bar(name, math, alpha = .7)
添加一些信息之后,生成了一個條形圖,如 圖38 所示:
創(chuàng)建 圖38 的完整代碼如下:
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
np.random.seed(100)
N = len(name)
math = np.random.randint(60, 100, N)
plt.figure(figsize=(9, 6))
plt.bar(name, math, alpha = .7)
plt.ylabel('Math Exam')
之后,使用以下代碼為物理、生物學和化學考試成績創(chuàng)建了更多模擬數(shù)據(jù)。
np.random.seed(100)
N = len(name)
math = np.random.randint(60, 100, N)
physics = np.random.randint(60, 100, N)
biology = np.random.randint(60, 100, N)
chemistry = np.random.randint(60, 100, N)
也可以使用 Pandas 創(chuàng)建一個表(在 Python 中,我們稱為 DataFrame )。從模擬數(shù)據(jù)創(chuàng)建的 DataFrame 如 圖39 所示:
默認情況下,這里沒有顯示有關如何創(chuàng)建 DataFrame 的代碼。
然后,將其可視化,如 圖40 所示:
創(chuàng)建 圖40 的代碼如下:
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
np.random.seed(100)
N = len(name)
math = np.random.randint(60, 100, N)
physics = np.random.randint(60, 100, N)
biology = np.random.randint(60, 100, N)
chemistry = np.random.randint(60, 100, N)
rows = 2
columns = 2
plt.figure(figsize=(12, 8))
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
plt.subplot(grid[0])
plt.bar(name, math, alpha = .7)
plt.ylabel('Math Exam')
plt.ylim(60, 100)
plt.subplot(grid[1])
plt.bar(name, physics, alpha = .7)
plt.ylabel('Physics Exam')
plt.ylim(60, 100)
plt.subplot(grid[2])
plt.bar(name, biology, alpha = .7)
plt.ylabel('Biology Exam')
plt.ylim(60, 100)
plt.subplot(grid[3])
plt.bar(name, chemistry, alpha = .7)
plt.ylabel('Chemistry Exam')
plt.ylim(60, 100)
或使用下面的代碼(如果要使用循環(huán)):
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
course_name = ['Math', 'Physics', 'Biology', 'Chemistry']
N = len(name)
rows = 2
columns = 2
plt.figure(figsize=(12, 8))
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
for i in range(len(course_name)):
np.random.seed(100)
course = np.random.randint(60, 100, N)
plt.subplot(grid[i])
plt.bar(name, course, alpha = .7)
plt.ylabel(course_name[i] + ' Exam')
plt.ylim(60, 100)
水平條形圖
可以使用下面的代碼來創(chuàng)建水平條形圖。
想以水平條形圖和各種顏色呈現(xiàn) 圖40,以下是生成它的完整代碼:
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
course_name = ['Math', 'Physics', 'Biology', 'Chemistry']
colors = ['#00429d', '#7f40a2', '#a653a1', '#c76a9f',
'#e4849c', '#d0e848']
N = len(name)
rows = 2
columns = 2
plt.figure(figsize=(12, 8))
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
for i in range(len(course_name)):
np.random.seed(100)
course = np.random.randint(60, 100, N)
plt.subplot(grid[i])
plt.barh(name, course, color = colors)
plt.xlabel(course_name[i] + ' Exam')
plt.xlim(60, 100)
plt.gca().invert_yaxis()
運行上面的代碼后,將獲得結(jié)果,如 圖41 所示:
可以使用以下參數(shù)在水平條形圖中插入誤差線:
N = len(name)
noise = np.random.randint(1, 3, N)
plt.barh(name, course, xerr = noise)
這里使用 1 到 3 之間的整數(shù)隨機數(shù)創(chuàng)建了誤差,如變量 noise 中所述。在為水平條形圖添加一些元素之后,將其顯示出來,如 圖42 所示:
創(chuàng)建 圖42 的代碼如下:
name = ['Adam', 'Barry', 'Corbin', 'Doe', 'Evans', 'Frans']
course_name = ['Math', 'Physics', 'Biology', 'Chemistry']
N = len(name)
rows = 2
columns = 2
plt.figure(figsize=(12, 8))
grid = plt.GridSpec(rows, columns, wspace = .25, hspace = .25)
np.random.seed(100)
for i in range(len(course_name)):
course = np.random.randint(60, 95, N)
noise = np.random.randint(1, 3, N)
plt.subplot(grid[i])
plt.barh(name, course, color = colors, xerr = noise,
ecolor = 'k')
plt.xlabel(course_name[i] + ' Exam')
plt.xlim(60, 100)
plt.gca().invert_yaxis()
也許已意識到模擬數(shù)據(jù)不是真實的,但是,我認為這仍然是理解 Matplotlib 中條形圖的一個很好的例子。
總結(jié)
本文是 Matplotlib 可視化介紹的第 1 部分。本文僅涵蓋 Matplotlib 介紹 11 個部分中的4個部分,包括散點圖,折線圖,直方圖和條形圖。在后續(xù)內(nèi)容中,我將展示如何創(chuàng)建箱形圖,小提琴圖,餅圖,極坐標圖,地理投影,3D圖和輪廓圖的教程。
原文來源:
https://towardsdatascience.com/visualizations-with-matplotlib-part-1-c9651008b6b8
下載1:leetcode 開源書
在「AI算法與圖像處理」公眾號后臺回復:leetcode,即可下載。每題都 runtime beats 100% 的開源好書,你值得擁有!
下載2 CVPR2020
在「AI算法與圖像處理」公眾號后臺回復:CVPR2020,即可下載1467篇CVPR 2020論文 個人微信(如果沒有備注不拉群!) 請注明:地區(qū)+學校/企業(yè)+研究方向+昵稱
覺得不錯就點亮在看吧

