matplotlib---7.坐標變換


一、matplotlib的坐標系

1.matplotlib的四個坐標系:

  1. 用戶級的data坐標系:坐標轉換對象為ax.transData。它是用戶級坐標系,由xlimylim控制
  2. Axes坐標系:坐標轉換對象為ax.transAxes。它是Axes的坐標系,(0,0)Axes的左下角,(1,1)Axes的右上角。
  3. Figure坐標系:坐標轉換對象為fig.transFigure。它是Figure的坐標系,(0,0)Figure的左下角,(1,1)Figure的右上角。
  4. 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)方法會返回pointdisplay坐標系下的坐標。其中point是點在data坐標系下的坐標(x,y)。你也可以給.transform()方法一次傳入多個點的坐標,此時輸出也是對應於display坐標系下的一系列坐標。

1.3 你可以對ax.trandData返回的坐標轉換對象調用.inverted()方法。該方法返回的是一個坐標逆轉換對象。對該坐標逆轉換對象調用.transform(point)方法會返回pointdata坐標系下的坐標。其中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) 

功能:返回一個混合坐標系

參數:

  1. x坐標為data坐標系,
  2. 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 有兩個函數返回特定的混合坐標系:

  1. matplotlib.axes.Axes.get_xaxis_transform():等價於matplotlib.transforms.blended_transform_factory(ax.transData, ax.transAxes)x坐標為data坐標系,y坐標為Axes坐標系。常用於繪制x軸的labeltickgridline
  2. matplotlib.axes.Axes.get_yaxis_transform():等價於matplotlib.transforms.blended_transform_factory(ax.transAxes,ax.transData)x坐標為Axes坐標系,y坐標為data坐標系。常用於繪制y軸的labeltickgridline

4.利用坐標變換制造陰影效果

4.1 matplotlib.transform.ScaledTranslation(xt, yt, scale_trans)創建一個新的坐標轉換對象,該坐標轉換由xtyt經過scale_trans坐標轉換而來。

它創建的是一個偏移對於的坐標變換。偏移的坐標是位於scale_trans中的。

  1. 制作陰影的時候,將陰影的zorder調小,從而使得陰影首先繪制並位於底層

  2. scale_transfig.dpi_scale_trans坐標轉換對象時,xt,yt的單位是像素。

  3. 還有一個方法也能達到同樣的效果: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可以為:

  1. linear:線性
  2. log:對數。其中basex|basey關鍵字指定對數的基
  3. logit:以2為底的對數
  4. 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)

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM