天天看點

Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

前言

matplotlib 提供的所有繪圖都帶有預設樣式。雖然這可以進行快速繪圖,但有時可能需要自定義繪圖的顔色和樣式,以對繪制更加精美、符合審美要求的圖像。matplotlib 的設計考慮到了此需求,很容易調整 matplotlib 圖形的樣式。

控制填充樣式

matplotlib 提供了填充圖案用于填充平面。這些填充圖案,對于僅包含黑白兩色的圖形中具有重要作用。

import numpy as np
import matplotlib.pyplot as plt
n = 10
a = np.random.random(n)
b = np.random.random(n)
x = np.arange(n)
plt.bar(x, a, color='w', hatch='x', edgecolor='black')
plt.bar(x, a+b, bottom=a, color='w', edgecolor='black', hatch='/')
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

Tips:具有填充呈現性的函數(如 pyplot.bar() )接受可選參數hatch控制填充樣式,此參數的可選值包括:"/", "\", "|", "-", "+", "x", "o", "O","."和"*",每個值對應于不同的填充圖案;edgecolor參數可用于控制圖案填充的顔色。

控制标記樣式

《詳解常見統計圖的繪制》

中,我們已經了解了如何如何繪制曲線,并明白了曲線是由點之間的連線構成的;此外,散點圖表示資料集中的每個點。而 matplotlib 提供了多種形狀,可以用其他類型的标記替換點的樣式。

标記的指定方式包括以下幾種:

1. 預定義标記:預定義的形狀,表示為 [0, 8] 範圍内的整數或某些預定義的字元串。

2.  頂點清單:值對清單,用作形狀路徑的坐标。

3. 正多邊形:表示 N 邊正多邊形的三元組 (N, 0, angle),其中 angle 為旋轉角度。

4. 星形多邊形:它表示為三元組 (N, 1, angle),代表 N 邊正星形,其中 angle 為旋轉角度。  

import numpy as np
import matplotlib.pyplot as plt
a = np.random.standard_normal((100, 2))
a += np.array((-1, -1))
b = np.random.standard_normal((100, 2))
b += np.array((1, 1))
plt.scatter(a[:,0], a[:,1], color = 'm', marker = 'x')
plt.scatter(b[:,0], b[:,1], color = 'c', marker = '^')
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

Tips:使用marker參數,可以為每個資料集合集合指定不同的标記。

我們已經在

《Matplotlib使用自定義顔色繪制統計圖》

中學習了如何在散點圖中為每個點定義不同的顔色,如果我們需要為每個點定義不同樣式該怎麼辦呢?問題在于,與 color 參數不同,marker 參數不接受标記樣式清單作為輸入。是以,我們不能實作 plt.scatter() 的單次調來顯示具有不同标記的多個點集。解決方案是,将每種類型的資料點分隔置不同集合中,并為每個集合單獨調用 pyplot.scatter() 調用:

import numpy as np
import matplotlib.pyplot as plt
label_list = (
    b'Iris-setosa',
    b'Iris-versicolor',
    b'Iris-virginica',
)
colors = ['c','y','m']
def read_label(label):
    return label_list.index(label)
data = np.loadtxt('iris.data', delimiter = ',', converters = { 4 : read_label })
marker_set = ('^', 'x', '.')
for i, marker in enumerate(marker_set):
    data_subset = np.asarray([x for x in data if x[4] == i])
    plt.scatter(data_subset[:,0], data_subset[:,1], color = colors[i], marker = marker)
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

對于 pyplot.plot(),也可以使用相同的标記參數通路标記樣式。當資料點密集時,每個點都使用标記進行顯示将會導緻圖檔混亂,是以 matplotlib 提供了 markevery 參數,允許每隔 N 個點顯示一個标記:  

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-6, 6, 1024)
y_1 = np.sinc(x)
y_2 = np.sinc(x) + 1
plt.plot(x, y_1, marker = 'x', color = '.75')
plt.plot(x, y_2, marker = 'o', color = 'k', markevery = 64)
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

控制标記大小

标記的大小可選參數 s 進行控制:

import numpy as np
import matplotlib.pyplot as plt
a = np.random.standard_normal((100, 2))
a += np.array((-1, -1))
b = np.random.standard_normal((100, 2))
b += np.array((1, 1))
plt.scatter(a[:,0], a[:,1], c = 'm', s = 100.)
plt.scatter(b[:,0], b[:,1], c = 'c', s = 25.)
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

Tips:标記的大小由 plt.scatter() 的參數 s 設定,但應注意它設定的是标記的表面積倍率而非半徑。

plt.scatter() 函數還可以接受清單作為s參數的輸入,其表示每個點對應一個大小:  

import numpy as np
import matplotlib.pyplot as plt
m = np.random.standard_normal((1000, 2))
r_list = np.sum(m ** 2, axis = 1)
plt.scatter(m[:, 0], m[:, 1], c = 'w', edgecolor='c', marker = 'o', s = 32. * r_list)
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

Tips:plt.plot() 函數允許在 markersize (或簡寫為 ms )參數的幫助下更改标記的大小,但是此參數不接受清單作為輸入。

建立自定義标記

雖然 matplotlib 提供了多種标記形狀。但是在某些情況下我們可能仍然找不到适合具體需求的形狀。例如,我們可能希望使用公司徽标等作為形狀。

在 matplotlib 中,将形狀描述為一條路徑——一系列點的連接配接。是以,如果要定義我們自己的标記形狀,必須提供一系列的點:  

import numpy as np
import matplotlib.path as mpath
from matplotlib import pyplot as plt
shape_description = [
    ( 1., 2., mpath.Path.MOVETO),
    ( 1., 1., mpath.Path.LINETO),
    ( 2., 1., mpath.Path.LINETO),
    ( 2., -1., mpath.Path.LINETO),
    ( 1., -1., mpath.Path.LINETO),
    ( 1., -2., mpath.Path.LINETO),
    (-1., -2., mpath.Path.LINETO),
    (-1., -1., mpath.Path.LINETO),
    (-2., -1., mpath.Path.LINETO),
    (-2., 1., mpath.Path.LINETO),
    (-1., 1., mpath.Path.LINETO),
    (-1., 2., mpath.Path.LINETO),
    ( 0., 0., mpath.Path.CLOSEPOLY),
]
u, v, codes = zip(*shape_description)
my_marker = mpath.Path(np.asarray((u, v)).T, codes)
data = np.random.rand(8, 8)
plt.scatter(data[:,0], data[:, 1], c = 'm', marker = my_marker, s = 75)
plt.show()      
Matplotlib自定義樣式繪制精美統計圖前言控制填充樣式控制标記樣式控制标記大小建立自定義标記

Tips:所有帶有标記的圖形的 pyplot 函數都有一個可選參數 marker,其參數值可以是預定義的 matplotlib 标記,也可以是自定義的路徑執行個體,路徑對象在 matplotlib.path 子產品中定義。

Path 對象的構造函數将坐标清單和指令清單作為輸入;每個坐标一條指令,使用一個清單将坐标和指令融合在一起,然後将坐标清單和指令傳遞給路徑構造函數,如下所示:

u, v, codes = zip(*shape_description)
my_marker = mpath.Path(np.asarray((u, v)).T, codes)      

形狀是通過光标的移動來描述的:

- MOVETO:此指令将光标移動到指定的坐标,并不畫線。

- LINETO:這将在光标目前點和目标點之間繪制直線,并将光标移動至目标點。

- CLOSEPOLY:此指令僅用于關閉路徑,每個形狀都以這條訓示結束。

理論上,任何形狀都是可能的,我們隻需要描述它的路徑。但在實踐中,如果想使用複雜的形狀,最好可以提前進行轉換工作。