一、matplotlib的
坐標系
1.matplotlib的四個坐標系:
- 用戶級的
data
坐標系:坐標轉換對象為ax.transData
。它是用戶級坐標系,由xlim
和ylim
控制 Axes
坐標系:坐標轉換對象為ax.transAxes
。它是Axes
的坐標系,(0,0)
為Axes
的左下角,(1,1)
為Axes
的右上角。Figure
坐標系:坐標轉換對象為fig.transFigure
。它是Figure
的坐標系,(0,0)
為Figure
的左下角,(1,1)
為Figure
的右上角。display
坐標系:它沒有坐標轉換對象。它顯示的是display
的像素坐標系,(0,0)
為display
的左下角,(width,height)
為display
的右上角。
前面三個坐標系的坐標轉換對象有方法執行坐標轉換,這些方法接受輸入並產生輸出:輸入為本坐標系內的坐標點,輸出為display
坐標系中的坐標。(因此display
坐標系沒有坐標轉換對象)。當然他們也有相關方法將來自於display
坐標系中的坐標轉換回本坐標系內的坐標。
2.在Artist
的構造函數中傳入transform
關鍵字參數(其值為坐標轉換對象),就能夠切換坐標系。如:ax.text(0.05,0.95,label,"This is a Text",transform=ax.transAxes)
,將Text
放置於Axes
坐標系中的(0.05,0.95)
位置處。
通常不建議直接使用
display
坐標系。因為它固定了絕對坐標,導致你resize
圖表時你必須重新定位坐標。所以你必須監聽resize
事件,非常麻煩。
1.用戶的data坐標系
1.1 當調用ax.set_xlimit(x_min,x_max)
以及ax.set_ylimit(y_min,y_max)
時,即建立起了用戶data
坐標系。左下角坐標為(x_min,y_min)
,右上角坐標為(x_max,y_max)
。
有時候你可能並沒有顯式調用
.set_xlimit()
以及.set_ylimit()
。其實matplotlib
會隱式調用它們來設置坐標軸的數據范圍。
import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.set_xlim(0, 10) ax.set_ylim(-1, 1) type(ax.transData) ax.transData.transform((5, 0))
1.2 你可以調用ax.transData
返回data
坐標系的坐標轉換對象。對該坐標轉換對象調用.transform(point)
方法會返回point
在display
坐標系下的坐標。其中point
是點在data
坐標系下的坐標(x,y)
。你也可以給.transform()
方法一次傳入多個點的坐標,此時輸出也是對應於display
坐標系下的一系列坐標。
1.3 你可以對ax.trandData
返回的坐標轉換對象調用.inverted()
方法。該方法返回的是一個坐標逆轉換對象。對該坐標逆轉換對象調用.transform(point)
方法會返回point
在data
坐標系下的坐標。其中point
是點在display
坐標系下的坐標(x,y)
。你也可以給.transform()
方法一次傳入多個點的坐標,此時輸出也是對應於data
坐標系下的一系列坐標。
1.4 當你調用了ax.set_xlim()
或者ax.set_ylim()
時,坐標轉換對象會實時更新。
import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.set_xlim(0,10) ax.set_ylim(-1,1) print(type(ax.transData)) # <class 'matplotlib.transforms.CompositeGenericTransform'> ax.transData.transform((5,0)) # data坐標對應的display坐標 array([221.4 , 144.72]) ax.transData.transform([(5,0),(1,2)]) # array([[221.4 , 144.72], [ 87.48, 362.16]]) inv = ax.transData.inverted() print(type(inv)) # <class 'matplotlib.transforms.CompositeGenericTransform'> inv.transform((221.4 , 144.72)) ax.set_ylim(-1,2) # 調整了ylimit ax.transData.transform((5,0)) # 相同的data坐標系內的點,display坐標改變 # array([221.4 , 108.48])
2.Axes坐標系
2.1 在Axes
坐標系中,(0,0)
位於Axes
的左下角,(1,1)
位於Axes
的右上角,(0.5,0.5)
位於Axes
的中心。當然你可以引用位於這之外的點,如(-0.1,1.1)
。
2.2 通常如果你需要在Axes
中放置一些文字說明,那么一般都是采用Axes
坐標系來定位。這樣無論圖形怎么縮放,這些Text
都能位於正確的位置。
2.3 你也可以在Axes
中通過Axes
坐標系添加一些Patch
,但是通常建議在data
坐標系下添加。因為你在Axes
中添加的圖表當圖表縮放時可能會出現問題。
3.混合坐標系(data坐標系+Axes坐標系)
3.1 有時候你需要混合data
坐標系和Axes
坐標系。
matplotlib.transforms.blended_transform_factory(ax.transData, ax.transAxes)
功能:返回一個混合坐標系
參數:
x
坐標為data
坐標系,y
坐標為Axes
坐標系。
因此該坐標系中(1,1)
表示的是data
坐標系中x=1
但是y
位於最上方的點。
舉例:
import matplotlib.pyplot as plt import matplotlib.transforms as tsf import matplotlib.patches as pth fig = plt.figure() ax = fig.add_subplot(111) trans = tsf.blended_transform_factory(ax.transData,ax.transAxes) rect = pth.Rectangle((1,0),width=1,height=1,transform=trans,color='yellow',alpha=0.5) ax.add_patch(rect) ax.set_xlim(0,4) ax.set_ylim(-4,4) plt.show()
3.2 有兩個函數返回特定的混合坐標系:
matplotlib.axes.Axes.get_xaxis_transform():
等價於matplotlib.transforms.blended_transform_factory(ax.transData, ax.transAxes)
。x
坐標為data
坐標系,y
坐標為Axes
坐標系。常用於繪制x
軸的label
、tick
、gridline
。matplotlib.axes.Axes.get_yaxis_transform():
等價於matplotlib.transforms.blended_transform_factory(ax.transAxes,ax.transData)
。x
坐標為Axes
坐標系,y
坐標為data
坐標系。常用於繪制y
軸的label
、tick
、gridline
。
4.利用坐標變換制造陰影效果
4.1 matplotlib.transform.ScaledTranslation(xt, yt, scale_trans)
創建一個新的坐標轉換對象,該坐標轉換由xt
和yt
經過scale_trans
坐標轉換而來。
它創建的是一個偏移對於的坐標變換。偏移的坐標是位於
scale_trans
中的。
-
制作陰影的時候,將陰影的
zorder
調小,從而使得陰影首先繪制並位於底層 -
當
scale_trans
為fig.dpi_scale_trans
坐標轉換對象時,xt
,yt
的單位是像素。 -
還有一個方法也能達到同樣的效果:
matplotlib.transforms.offset_copy(trans,x=xt,y=yt,units='inches')
,但是該方法返回的坐標轉換對象是trans
合成了偏移之后的效果。
舉例:
import matplotlib.pyplot as plt import matplotlib.transforms as transforms import matplotlib.patches as patches fig = plt.figure() ax = fig.add_subplot(111) line, = ax.plot([1,2,3,4],[1,2,2,1],lw=3,color='blue') dx,dy = 2/72. , -2/72. # 偏移量 offset = transforms.ScaledTranslation(dx,dy,fig.dpi_scale_trans) shadow_transform = ax.transData + offset ax.plot([1,2,3,4],[1,2,2,1],lw=3,color='gray',transform=shadow_transform,zorder=0.5*line.get_zorder())#陰影 plt.show()
5.直角坐標系、對數坐標系、極坐標系
5.1 設置x
軸/y
軸是否對數坐標
通過Axes.set_xscale(value,**kwargs)
/Axes.set_yscale(value,**kwargs)
方法可以設置x
軸/y
軸是否對數坐標。其中value
可以為:
linear
:線性log
:對數。其中basex
|basey
關鍵字指定對數的基logit
:以2為底的對數symlog
:對數,其中basex
|basey
關鍵字指定對數的基
你也可以通過matplotlib.pyplot.xscale()
和matplotlib.pyplot.yscale()
來設置對數坐標。一定要先添加數據后設置對數坐標。
舉例:
import numpy as np import matplotlib.pyplot as plt y = np.random.normal(loc=0.5,scale=0.4,size=1000) y = y[(y>0) & (y<1)] y.sort() x = np.arange(len(y)) plt.figure(figsize=(12,8)) plt.subplot(221) plt.plot(x,y) plt.grid(True) plt.subplot(222) plt.plot(x,y) plt.yscale('log') plt.grid(True) plt.subplot(223) plt.plot(x,y-y.mean()) plt.yscale('symlog',linthreshy=0.05) plt.grid(True) plt.subplot(224) plt.plot(x,y) plt.yscale('logit') plt.grid(True) plt.tight_layout() plt.show()
5.2 創建極坐標的Axes
通過Figure.add_axes((left,bottom,width,height), projection='polar')
或者Figure.add_axes((left,bottom,width,height), polar=True)
方法可以創建一個極坐標的Axes
。其中polar
關鍵字是為了兼容舊代碼,新代碼推薦用projection
關鍵字,因為projection
關鍵字不僅可以設置極坐標,還可以設置自定義坐標(它將坐標統一為映射關系)。
Figure.add_subplot(...)
也是同樣的設置
舉例:
import matplotlib.pyplot as plt fig = plt.figure(figsize=(12,8)) ax = fig.add_subplot(111,projection='polar') theta = np.arange(0,2*np.pi,0.02) ax.plot(theta,2*np.ones_like(theta),lw=2) ax.plot(theta,theta/6,'--',lw=2)