圖表有很多個組成部分,例如標題、x/y軸名稱、大刻度小刻度、線條、數據點、注釋說明等等。
我們來看官方給的圖,圖中標出了各個部分的英文名稱
Matplotlib提供了很多api,開發者可根據需求定制圖表的樣式。
前面我們設置了標題和x/y軸的名稱,本文介紹更多設置其他部分的方法。
繪圖
先繪制一個事例圖。然后以此為基礎進行定制。
def demo2():
x_list = []
y_list = []
for i in range(0, 365):
x_list.append(i)
y_list.append(math.sin(i * 0.1))
ax = plt.gca()
ax.set_title('rustfisher.com mapplotlib example')
ax.set_xlabel('x')
ax.set_ylabel('y = sin(x)')
ax.grid()
plt.plot(x_list, y_list)
plt.show()
if __name__ == '__main__':
print('rustfisher 圖表講解')
demo2()
運行得到
紅色框框里的是figure;綠色框框里的叫做ax。
代碼中ax = plt.gca()
獲取到的就是綠色框框里的部分(對象)。
Figure 大圖
Figure代表整張圖,暫時稱為“全圖”或者“大圖”。一張圖里可以有多個子圖表。最少必須要有一個圖表。像上面那樣。
Axes 數據圖
一張張的圖,圖里顯示着數據,暫稱為“數據圖”。一個大圖里可以有多個數據圖。但單個數據圖對象只能在1個大圖里。
多張數據圖 subplots
例如同時存在2個數據圖
def demo_subplot():
x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
x_list.append(i)
y_list.append(math.sin(i * 0.1))
y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('rustfisher.com 1')
ax2.set_title('rustfisher.com 2')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')
ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
plt.show()
調用subplots()
接口,傳入數字指定要多少張數據圖。
返回的多張圖要用括號括起來。每個數據圖可以繪制(plot
)不同的數據。
標題用set_title()
來設置。
可以看到上下兩張圖太擠了,有重疊部分。可以在plt.show()
之前加一個fig.tight_layout()
讓它們拉開一點距離。
坐標軸
對於2維數據圖,它有2個坐標,橫坐標和縱坐標。有一些接口可以設置參數。
例如控制坐標軸的名字set_xlabel()
set_ylabel
;
顯示數據范圍
set_xlim
方法可以控制x軸數據顯示范圍。同理y軸用set_ylim
來控制。
對於顯示范圍,set_xlim
方法主要參數為left
和right
;或者用xmin
xmax
。這兩套不能同時使用。
set_ylim
主要參數是top
bottom
;或者ymin
ymax
。這兩套不能同時使用。
增加顯示范圍控制的代碼
def demo3():
x_list = []
y_list = []
y2_list = []
for i in range(0, 365):
x_list.append(i)
y_list.append(math.sin(i * 0.1))
y2_list.append(math.cos(i * 0.1))
fig, (ax1, ax2) = plt.subplots(2)
ax1.set_title('rustfisher.com 1')
ax1.set_xlabel('x')
ax1.set_ylabel('y = sin(x)')
ax2.set_title('rustfisher.com 2')
ax2.set_xlabel('x')
ax2.set_ylabel('y = cos(x)')
ax1.set_xlim(left=50, right=200.6) # 控制x軸顯示范圍
ax1.set_ylim(top=1, bottom=0.3) # 控制y軸顯示范圍
ax2.set_xlim(xmin=1, xmax=156.6) # 控制x軸顯示范圍
ax2.set_ylim(ymin=-0.3, ymax=0.3) # 控制y軸顯示范圍
ax1.plot(x_list, y_list)
ax2.plot(x_list, y2_list)
fig.tight_layout()
plt.show()
運行結果
刻度
tick意思是標記。在坐標軸上的是刻度。Major tick暫稱為大刻度,minor tick暫稱為小刻度。
使用set_xticks
方法控制刻度顯示。傳入的列表是我們希望顯示的刻度。
minor
參數默認為False,不顯示小刻度。
關鍵代碼如下
ax1.set_xticks([50, 60, 70, 150])
ax1.set_yticks([0.1, 0.2, 0.3, 0.7, 0.9])
ax1.grid() # 顯示格子
ax2.set_xticks([1, 60, 70, 150], minor=True)
ax2.set_yticks([-0.1, 0, 0.1, 0.3], minor=True)
ax2.grid()
可見當minor=True
,傳入的刻度列表有可能不顯示。
也可以控制大刻度上的文字旋轉
plt.setp(ax1.xaxis.get_majorticklabels(), rotation=-45)
plt.setp(ax2.xaxis.get_majorticklabels(), rotation=-60)
邊線 spine
spine是脊柱的意思,這里我們先稱為邊線。有上下左右4條邊線。名稱是top
bottom
left
right
可以直接從圖表對象獲取它的邊線,比如右邊線ax1.spines.right
。
一些簡單的操作,例如
set_visible
顯示和隱藏set_ticks_position
刻度顯示的位置set_bounds
邊線顯示范圍set_linewidth
線的寬度
隱藏右邊線和上邊線
ax1.spines.right.set_visible(False)
ax1.spines.top.set_visible(False)
讓刻度顯示在右邊和上方
ax2.yaxis.set_ticks_position('right')
ax2.xaxis.set_ticks_position('top')
設置邊線顯示范圍
ax3.spines.left.set_bounds(-0.5, 0.5)
ax3.spines.top.set_bounds(340, 400)
設置線的寬度
ax3.spines.bottom.set_linewidth(2)
完整代碼如下
import math
import matplotlib.pyplot as plt
def demo_spine():
x_list = []
y_list = []
for i in range(0, 365):
x_list.append(i)
y_list.append(math.sin(i * 0.1))
fig, (ax1, ax2, ax3) = plt.subplots(3)
ax_list = [ax1, ax2, ax3]
for i in range(0, 3):
cur_ax = ax_list[i]
cur_ax.set_title('rustfisher.com ' + str(i))
cur_ax.plot(x_list, y_list)
cur_ax.set_xlabel('x')
cur_ax.set_ylabel('y = sin(x)')
ax1.spines.right.set_visible(False)
ax1.spines.top.set_visible(False)
ax2.spines.bottom.set_visible(False)
ax2.spines.left.set_visible(False)
ax2.yaxis.set_ticks_position('right')
ax2.xaxis.set_ticks_position('top')
ax3.spines.left.set_bounds(-0.5, 0.5)
ax3.spines.top.set_bounds(340, 400)
ax3.spines.bottom.set_linewidth(2)
fig.tight_layout()
plt.show()
運行截圖
數據點
控制數據點的樣式。下面我們在一張圖表里繪制多條數據線。
def demo_line():
x_list = []
y_list = []
y2_list = []
y3_list = []
for i in range(0, 20):
x_list.append(i)
y_list.append(math.sin(i) * 2 - 4)
y2_list.append(math.sin(i) * 2)
y3_list.append(math.cos(i) * 1.3 + 3)
plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
plt.plot(x_list, y2_list, 'go', linewidth=1)
plt.plot(x_list, y3_list, 'r+')
plt.show()
plot()
方法中,支持多種選項。
linestyle
支持的選項
'-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted'
注釋 legend
添加注釋,調用lengend()
方法。
在前面代碼基礎上添加
plt.plot(x_list, y_list, color='blue', linestyle='-.', linewidth=2, markersize=4)
plt.plot(x_list, y2_list, 'go', linewidth=1)
plt.plot(x_list, y3_list, 'r+')
plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'])
控制注釋顯示的地方,添加bbox_to_anchor
和bbox_transform
屬性
plt.legend(['math.sin(i) * 2 - 4', 'math.sin(i) * 2', 'math.cos(i) * 1.3 + 3'], bbox_to_anchor=(1, 1),
bbox_transform=plt.gcf().transFigure)
中文亂碼問題
在設置標題用到中文的時候,可能會出現亂碼。
可以設置rcParams
的字體,解決亂碼問題。
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
至此,我們把圖表中各個部分都簡要介紹了一下。
參考
本例環境
- macOS
- PyCharm CE
- Python3
參考資料
- 【運營的Python指南】繪制圖表Matplotlib快速入門
- Python筆記 https://rustfisher.com/categories/Python/
- matplotlib https://matplotlib.org/