python 坐标轴刻度_给妹子讲python-S02E08坐标轴与主次刻度
微信公眾號: python數據科學家
【要點搶先看】
1.剖析plt和坐標軸對象ax的關系
2.主刻度與次刻度的概念
3.格式生成器與定位器的概念
4.數值型主次刻度與自定義格式生成器函數舉例
5.日期型主次刻度舉例
這一集,我們專門來談談坐標軸的有關內容,先看以下兩段代碼,他們實現的是同樣的功能:繪制正余弦兩個子圖:
代碼一:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,1000)
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x)) #用plt繪制第一個子圖
plt.subplot(2,1,2)
plt.plot(x,np.cos(x)) #用plt繪制第二個子圖
plt.show()
代碼二:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,1000)
fig, ax = plt.subplots(2,1)
ax[0].plot(x, np.sin(x)) #用對應的坐標軸對象畫第一個子圖
ax[1].plot(x, np.cos(x)) #用對應的坐標軸對象畫第二個子圖
plt.show()
可以看出,這兩段代碼所達到的效果是一樣的。代碼段一采用的是MATLAB風格的接口,這是由于Matplotlib最初是作為MATLAB替代品的歷史緣故。MATLAB風格的工具位于pyplot 即plt接口中,因此我們可以采用plt.plot函數來進行繪圖。這種接口最重要的特征就是“有狀態”:他表征當前所位于的子圖狀態,并持續跟蹤當前的圖形和坐標軸。并可以通過plt.gcf()獲取當前的活動Figure對象,利用plt.gca()獲取當前活動的axes坐標軸對象。
而代碼段二所采用的是完全不同的第二種模式,即面向對象接口,他在繪圖的過程之中不再受到當前所謂“活動”圖形及坐標軸的限制,因為他一次性就從subplots函數中獲取了表征所有坐標軸的ax數組和Figure對象。
補充一點,坐標軸對象ax包含了橫軸、縱軸所包圍的區域內的一切(各坐標軸、刻度、標簽、圖形等)
我最后來說說plt和ax二者的聯系,plt的絕大多數方法都有ax的對應版本,有的一模一樣,有的稍作改變:
plt.plot() = ax.plot()
plt.legend() = ax.legend()
plt.xlabel()/ylabel()/xlim()/ylim()/title() =
ax.setxlabel()/setylabel()/setxlim()/set_ylim()/set_title()
當然,如果用ax來設置這些參數的話,可以放在一個函數中,用多個關鍵字進行表征和設置
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,1000)
ax = plt.axes()
ax.plot(x,np.sin(x))
ax.set(xlim=(0,10), ylim=(-2,2), xlabel='x', ylabel='sin(x)',title='plot sin(x)')
plt.show()
值得一提的是,在代碼段一中我們還可以通過ax = plt.subplot(2, 1, 1)或ax = plt.gca()這兩種方法來獲得當前的坐標軸對象ax。
強化了坐標軸ax的概念之后,我們再進入今天另一個重要的話題,坐標軸的主次刻度。
每一個坐標軸都有主要刻度線與次要刻度線。主要刻度更大更顯著,而次要刻度往往更小。主刻度都顯示為一個較大的刻度線和標簽,而次要刻度都顯示為一個較小的刻度線,而不顯示標簽。主次刻度這件事兒,大家想想我們用過的尺子就知道了,厘米的地方刻度要長而明顯,并且有數字標識,而毫米的地方刻度則要短,并且沒有數字標識。這么做既能滿足刻度線的完整性,又能突出刻度標識的重點。
我們先舉一個例子:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter
fig = plt.figure()
xmajorLocator = MultipleLocator(20) # 將x主刻度標簽設置為20的倍數
xmajorFormatter = FormatStrFormatter('%1.1f') # 設置x軸標簽文本的格式
xminorLocator = MultipleLocator(5) # 將x軸次刻度標簽設置為5的倍數
ymajorLocator = MultipleLocator(0.5) # 將y軸主刻度標簽設置為0.5的倍數
ymajorFormatter = FormatStrFormatter('%1.1f') # 設置y軸標簽文本的格式
yminorLocator = MultipleLocator(0.1) # 將此y軸次刻度標簽設置為0.1的倍數
ax = plt.subplot(111)
ax.xaxis.set_major_locator(xmajorLocator)
ax.xaxis.set_major_formatter(xmajorFormatter)
ax.yaxis.set_major_locator(ymajorLocator)
ax.yaxis.set_major_formatter(ymajorFormatter)
# 顯示次刻度標簽的位置,沒有標簽文本
ax.xaxis.set_minor_locator(xminorLocator)
ax.yaxis.set_minor_locator(yminorLocator)
ax.xaxis.grid(True, which='major') # x坐標軸的網格使用主刻度
ax.yaxis.grid(True, which='minor') # y坐標軸的網格使用次刻度
t = np.arange(100)
s = np.sin(0.1*np.pi*t)*np.exp(-t*0.01)
plt.plot(t,s,'--r*')
plt.show()
這個例子中,我們設置了主刻度線和次刻度線,其中x軸主刻度線是20的整數倍,并且標明了刻度值,而次要刻度線是5的整數倍,省去了刻度值。y軸同理。
這里的核心是定位器和格式生成器兩個概念,我們先分別生成X軸的主定位器、主格式生成器,再生成X軸的次定位器(由于X軸次要坐標沒有刻度值,所以省去了次要格式生成器)
然后再利用坐標軸ax的xaxis.set_major_locator、xaxis.set_major_formatter和xaxis.set_minor_locator方法,分別對定位器和格式生成器進行賦值。
總結一下:我們就是通過定義每個坐標軸的locator和formatter對象,來完成刻線位置和標簽這些屬性的設置。
我們再看一個更復雜的例子
我們之前在繪制正余弦曲線圖的時候,橫坐標的刻度值都是整數1,2,3等等,按道理來說我們更想以
為度量,那么我們仿照上面的例子來做:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
x = np.linspace(0, 3*np.pi, 100)
plt.plot(x,np.sin(x))
ax = plt.axes()
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi/2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi/4))
plt.show()
基本上是那么個意思,主刻度是π/2的倍數,次刻度是π/4的刻度,但是用的是小數顯示,如果想更直觀的直接在圖上顯示π,怎么做?肯定還是要在格式生成器類上做文章,因為沒有內置的合適生成器滿足我們的要求,這里我們要用到自定義函數設置不同刻度的標簽顯示。這里我們讀取實際的刻度值,用自定義函數將其轉換為相應的π表達式。
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator
def format_func(value, tick_number):
N = int(np.round(2 * value / np.pi))
if N == 0:
return '0'
elif N == 1:
return r"$\pi/2$"
elif N == 2:
return r"$\pi$"
elif N % 2 > 0:
return r"${}\pi/2$".format(N)
else:
return r"${}\pi$".format(N//2)
x = np.linspace(0, 3*np.pi, 100)
plt.plot(x,np.sin(x))
ax = plt.axes()
ax.xaxis.set_major_locator(plt.MultipleLocator(np.pi/2))
ax.xaxis.set_minor_locator(plt.MultipleLocator(np.pi/4))
ax.xaxis.set_major_formatter(plt.FuncFormatter(format_func))
ax.grid(True)
plt.show()
最后一部分,我們來談談日期型主次刻度。
一般來說,我們在處理時間序列的數據時,常常需要處理日期型X坐標值,比如一整年的特定數據,如果我們在X軸上將每天的刻度都標識出來,一來太擁擠,二來也沒太大必要,一般我們會選取一些大的時間節點作為主刻度線,比如每月1日,或者固定的每周幾。我們分別舉兩個例子來實現這兩種情況
首先我們把每月1日設置為主刻度,可以利用MonthLocator作為定位器,DateFormatter作為格式生成器。
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import datetime
fig = plt.figure()
start = datetime.datetime(2017, 1, 1)
end = datetime.datetime(2018, 1, 1)
delta = datetime.timedelta(days=1)
dates = mpl.dates.drange(start, end, delta) #生成matplotlib指定的日期橫軸
y = np.random.rand(len(dates))*0.4+0.5
ax = plt.subplot(111,ylim=(0,1))
ax.plot_date(dates,y,linestyle='-',marker='.')
ax.xaxis.set_major_locator(mpl.dates.MonthLocator())
ax.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y-%m'))
ax.grid(True)
fig.autofmt_xdate() # 自動旋轉日期標記,用以適應橫軸空間
plt.show()
再補充強調幾個細節,一是我們把日期格式只設置成了年月的形式,表示每個月的第一天。并且設置了自動旋轉角度來適應橫軸空間。同時我們發現,我們需要mpl.dates.drange方法來專門形成matplotlib繪圖時可以識別的日期序列。
最后一個例子中我們以周為觀測單元,我們設置主刻度為每周一,次要刻度為每天。
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import datetime
from matplotlib.dates import DateFormatter, WeekdayLocator, DayLocator, MONDAY
start = datetime.datetime(2017, 1, 1)
end = datetime.datetime(2017, 4, 1)
delta = datetime.timedelta(days=1)
dates = mpl.dates.drange(start, end, delta)
y = np.random.rand(len(dates))*0.4+0.5
fig,ax = plt.subplots(1)
ax.plot_date(dates,y,linestyle='-',marker='.')
mondays = WeekdayLocator(MONDAY)
alldays = DayLocator()
ax.xaxis.set_major_locator(mondays)
ax.xaxis.set_minor_locator(alldays)
mondayFormatter = DateFormatter('%Y-%m-%d')
ax.xaxis.set_major_formatter(mondayFormatter)
ax.grid(True)
fig.autofmt_xdate()
plt.show()
從代碼中我們可以看出,這里使用了周定位器WeekdayLocator,和日定位器DayLocator,主刻度格式設置為完整的年月日,其他的原理和之前都是一樣的。
【妹子說】很實用,刻度看起來確實是繪圖中不可忽視的一個重要細節!
總結
以上是生活随笔為你收集整理的python 坐标轴刻度_给妹子讲python-S02E08坐标轴与主次刻度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python伪装浏览器https_pyt
- 下一篇: python获取指定端口流量_利用pyt