【實驗樓/matplotlib.pyplot】繪製笛卡爾座標系+註釋+圖例

博主的github鏈接,歡迎大家來訪問~:https://github.com/Sh-Zh-7

強化學習經典算法實現地址:https://github.com/Sh-Zh-7/reinforce-learning-impl

一. 問題描述

二. 問題分析

做這種問題我們應該先把圖的大致模樣畫出來,然後再去考慮細節。

這裏一個比較難的點是笛卡爾直角座標系的繪製,因爲我們默認的圖都是使用矩形狀的座標系的。

稍微總結一下,大概可以分這麼幾步走:

  1.  繪製直角座標系
  2.  繪製兩個三角函數
  3.  繪製兩條直線
  4.  繪製annotation
  5. 繪製圖例

下面,我就一步一步來實現它。

 

三. 繪製直角座標系

這裏我介紹兩種方法。

第一種在矩形圖上直接修改的。主要是把右邊和上面的兩條矩形邊界給抹除了。

# 在這裏我不得不吐槽matplotlib的官方文檔做的實在是太不好了
# 很多api都只有聲明和源碼,沒有具體的解釋
# 想要找到具體的用法只能是在網上找博客
import numpy as np
import matplotlib.pyplot as plt

# 創建畫板和畫布對象
plt.figure(figsize=(8, 5), dpi=80)
ax = plt.subplot(111)

# 這次不整個消失了
# 我們選擇將右邊及上面的矩形邊框刪除掉
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# 設置座標軸上數據的方向
# 0是和我們普通笛卡爾座標系相一致的,1則是相反的
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))

第二種就是使用mpl_axisartist。這個模塊專門是用來繪製座標軸的。

其功能十分強大,還可以給我們的座標軸添加上正方向的箭頭添加一些註釋啊什麼的。

import numpy as np #導入數值計算模塊
import matplotlib.pyplot as plt #導入繪圖模塊
import mpl_toolkits.axisartist as axisartist #導入座標軸加工模塊

fig=plt.figure() #新建畫布
ax=axisartist.Subplot(fig,111) #使用axisartist.Subplot方法創建一個繪圖區對象ax
fig.add_axes(ax) #將繪圖區對象添加到畫布中

ax.axis[:].set_visible(False) #隱藏原來的實線矩形

ax.axis["x"]=ax.new_floating_axis(0,0,axis_direction="bottom") #添加x軸
ax.axis["y"]=ax.new_floating_axis(1,0,axis_direction="bottom") #添加y軸

ax.axis["x"].set_axisline_style("->",size=1.0) #給x座標軸加箭頭
ax.axis["y"].set_axisline_style("->",size=1.0) #給y座標軸加箭頭
ax.annotate(s='x' ,xy=(2*math.pi,0) ,xytext=(2*math.pi,0.1)) #標註x軸
ax.annotate(s='y' ,xy=(0,1.0) ,xytext=(-0.5,1.0)) #標註y軸

(P.S. 如果是使用pyplot中的subplots方法,是不會成功的;所以老老實實使用axisartist方法把!

 

四. 繪製我們的函數圖像

很顯然我們得使用我們的plot函數,這裏順便提一下我們plot函數的三種用法

  1.  給定X和Y的所有點,繪製矢量曲線圖
  2. 直接給定一個X和關於X的函數(e.g. X + 1), 根據表達式的內容來繪製。
  3. 傳入兩個list,每一個list中有兩個元素,分別是x或者y的起始和終末位置;按照這兩個座標來繪製直線

繪製sin和cos的話我們使用第一個方法,繪製後面的linestyle爲"--"的直線我們使用第三個方法。

我們可以使用Python的sequence unpacking來簡單賦值

# 準備數據,利用sequence unpacking
X  = np.linspace(-np.pi, np.pi, 100, endpoint=True) # 這個endpoint非常細節
C, S = np.cos(X), np.sin(X)

# 繪製圖像
plt.plot(X, C, color='b', label="Cos Function")
plt.plot(X, S, color='r', label="Sin Function")
# 繪製linestyle="--"的兩條直線
t = np.pi * 2 / 3;
plt.plot([t, t], [0, np.sin(t)], color='r', linestyle="--")
plt.plot([t, t], [0, np.cos(t)], color='b', linestyle="--")

 

五. 修改座標系上的刻度

這裏我們要做兩件事:

  1.  確定整條座標軸所能表示的範圍。——plt.xlim, plt.ylim
  2.  確定座標軸上哪些數字要被特別表示,然後還要標出來。——plt.xticks, plt.yticks
# 修改圖中座標系表示的最大和最小值
plt.xlim(X.min() * 1.1, X.max() * 1.1)
plt.ylim(-1.1, 1.1)

# 修改座標軸上的標籤
x_numbers = [-np.pi, -np.pi / 2, 0, np.pi / 2, np.pi]
x_labels = [r"$-\pi$", r"$-\pi$", r"$0$", r"$\pi/2$", r"$\pi$"] # python中使用LaTex得加上$$, 最好向他這樣轉義
plt.xticks(x_numbers, x_labels)
y_numbers = [-1, 1]
y_labels = ["-1", "1"]
plt.yticks(y_numbers, y_labels)

 

六.  繪製註釋

繪製那兩個散點我們就不提了,這裏直接講怎麼繪製註釋:

從matplotlib中我們發現:

  1. xy是你在圖中要註釋的點。
  2. xytext是註釋的位置。
  3. xycoords和textcoords似乎是各種偏移量?反正這個用默認值就好
  4. arrorprops是箭頭。
# 補充記號
plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$',
             xy=(t, np.sin(t)), xycoords='data',
             xytext=(+10, +30), textcoords='offset points', fontsize=16,
             arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))
plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$',
             xy=(t, np.cos(t)), xycoords='data',
             xytext=(-90, -50), textcoords='offset points', fontsize=16,
             arrowprops=dict(arrowstyle="->", connectionstyle="arc3,rad=.2"))

 

七. 繪製圖例

圖例的繪製也是一個plot.legend了事,不過這裏我不會這麼講。

我想提的是:如果你在之前plot中給定了label的時候,這裏就不需要顯示給定label

只要傳入關鍵字參數,把我們的邊框消除掉即可

# 設置圖例
# 如果上面制定了label, 那這裏就不用傳入列表!
plt.legend(frameon=False)

 

八. 源碼

https://labfile.oss.aliyuncs.com/courses/892/sin_cos_functions.py

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章