python中用Matplotlib做多個縱軸 (多y軸)


Matlab里做多給軸的函數很直接,雙軸是plotyy, 三軸是plotyyy, 四軸是plot4y,更多應該是multiplotyyy。

而matplotlib似乎可以用figure.add_axes()來實現,探索中……

 
        

多軸繪制的圖層原理

關於Matplotlib的圖層

圖層可分為四種

  • Canvas層 畫布層 位於最底層,用戶一般接觸不到。 matplotlib.pyplot就是一個canvas層
  • Figure層 圖像層 建立在Canvas之上。 plt.figure()就是一個figure層
  • Axes層 坐標層 建立在Figure之上。fig.add_axes(ax)就加一個Axes層ax在figure上,這時就可以畫出一個空白的坐標了。
  • plot層 繪制層 坐標軸、圖例等輔助信息層以及圖像層都是建立在Axes之上

【2018-5-14】

多軸的繪制要用到有兩種方法可以實現,一是用主軸和寄生軸的方法,即mpl_toolkits.axisartist.parasite_axes里的HostAxes,和ParasiteAxes。 另一種是用twinx(),結合mpl_toolkits.axes_grid1里的host_subplot。 這里用寄生軸的方法實現。

首先是要創建主軸用HostAxes(figure,[ 左,下,寬,高 ]) 然后寄生出獨立的y軸來,並共享x軸。獨立的y軸對應獨立的曲線 將寄生軸加入主軸的列表

第一根寄生軸可以直接借用原坐標的右軸,所以不需要新增軸 如果需要兩個以上的y軸,第三個y軸就要新建固定軸了,要用到get_grid_helper().new_fixed_axis 設置第三及更多Y軸的偏移量 將主軸裝載到figure上 設置軸的外面特性,比如顏色,刻度范圍等

 

from mpl_toolkits.axisartist.parasite_axes import HostAxes, ParasiteAxes
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(1) #定義figure,(1)中的1是什么
ax_cof = HostAxes(fig, [0, 0, 0.9, 0.9])  #用[left, bottom, weight, height]的方式定義axes,0 <= l,b,w,h <= 1

#parasite addtional axes, share x
ax_temp = ParasiteAxes(ax_cof, sharex=ax_cof)
ax_load = ParasiteAxes(ax_cof, sharex=ax_cof)
ax_cp = ParasiteAxes(ax_cof, sharex=ax_cof)
ax_wear = ParasiteAxes(ax_cof, sharex=ax_cof)

#append axes
ax_cof.parasites.append(ax_temp)
ax_cof.parasites.append(ax_load)
ax_cof.parasites.append(ax_cp)
ax_cof.parasites.append(ax_wear)



#invisible right axis of ax_cof
ax_cof.axis['right'].set_visible(False)
ax_cof.axis['top'].set_visible(False)
ax_temp.axis['right'].set_visible(True)
ax_temp.axis['right'].major_ticklabels.set_visible(True)
ax_temp.axis['right'].label.set_visible(True)

#set label for axis
ax_cof.set_ylabel('cof')
ax_cof.set_xlabel('Distance (m)')
ax_temp.set_ylabel('Temperature')
ax_load.set_ylabel('load')
ax_cp.set_ylabel('CP')
ax_wear.set_ylabel('Wear')

load_axisline = ax_load.get_grid_helper().new_fixed_axis
cp_axisline = ax_cp.get_grid_helper().new_fixed_axis
wear_axisline = ax_wear.get_grid_helper().new_fixed_axis

ax_load.axis['right2'] = load_axisline(loc='right', axes=ax_load, offset=(40,0))
ax_cp.axis['right3'] = cp_axisline(loc='right', axes=ax_cp, offset=(80,0))
ax_wear.axis['right4'] = wear_axisline(loc='right', axes=ax_wear, offset=(120,0))

fig.add_axes(ax_cof)

''' #set limit of x, y
ax_cof.set_xlim(0,2)
ax_cof.set_ylim(0,3)
'''

curve_cof, = ax_cof.plot([0, 1, 2], [0, 1, 2], label="CoF", color='black')
curve_temp, = ax_temp.plot([0, 1, 2], [0, 3, 2], label="Temp", color='red')
curve_load, = ax_load.plot([0, 1, 2], [1, 2, 3], label="Load", color='green')
curve_cp, = ax_cp.plot([0, 1, 2], [0, 40, 25], label="CP", color='pink')
curve_wear, = ax_wear.plot([0, 1, 2], [25, 18, 9], label="Wear", color='blue')


ax_temp.set_ylim(0,4)
ax_load.set_ylim(0,4)
ax_cp.set_ylim(0,50)
ax_wear.set_ylim(0,30)

ax_cof.legend()

#軸名稱,刻度值的顏色
#ax_cof.axis['left'].label.set_color(ax_cof.get_color())
ax_temp.axis['right'].label.set_color('red')
ax_load.axis['right2'].label.set_color('green')
ax_cp.axis['right3'].label.set_color('pink')
ax_wear.axis['right4'].label.set_color('blue')

ax_temp.axis['right'].major_ticks.set_color('red')
ax_load.axis['right2'].major_ticks.set_color('green')
ax_cp.axis['right3'].major_ticks.set_color('pink')
ax_wear.axis['right4'].major_ticks.set_color('blue')

ax_temp.axis['right'].major_ticklabels.set_color('red')
ax_load.axis['right2'].major_ticklabels.set_color('green')
ax_cp.axis['right3'].major_ticklabels.set_color('pink')
ax_wear.axis['right4'].major_ticklabels.set_color('blue')

ax_temp.axis['right'].line.set_color('red')
ax_load.axis['right2'].line.set_color('green')
ax_cp.axis['right3'].line.set_color('pink')
ax_wear.axis['right4'].line.set_color('blue')

plt.show()

結果是這樣的:

 

 
        
以下是摸索過程中的練習,給自己紀錄一下。
用一個修改了的官方例子來說明一下, jupyter notebook 代碼如下:
%matplotlib inline

from mpl_toolkits.axisartist.parasite_axes import HostAxes, ParasiteAxes
import matplotlib.pyplot as plt

 
         

fig = plt.figure(1)

 
         

host = HostAxes(fig, [0.15, 0.1, 0.65, 0.8])
par1 = ParasiteAxes(host, sharex=host)
par2 = ParasiteAxes(host, sharex=host)
host.parasites.append(par1)
host.parasites.append(par2)

 
         

host.set_ylabel('Denstity')
host.set_xlabel('Distance')

 
         

host.axis['right'].set_visible(False)
par1.axis['right'].set_visible(True)
par1.set_ylabel('Temperature')

 
         

par1.axis['right'].major_ticklabels.set_visible(True)
par1.axis['right'].label.set_visible(True)

 
         

par2.set_ylabel('Velocity')
offset = (60, 0)
new_axisline = par2._grid_helper.new_fixed_axis  # "_grid_helper"與"get_grid_helper()"等價,可以代替

#new_axisline = par2.get_grid_helper().new_fixed_axis  # 用"get_grid_helper()"代替,結果一樣,區別目前不清楚
par2.axis['right2'] = new_axisline(loc='right', axes=par2, offset=offset)

 
         

fig.add_axes(host)

 
         

host.set_xlim(0,2)
host.set_ylim(0,2)

 
         

host.set_xlabel('Distance')
host.set_ylabel('Density')
host.set_ylabel('Temperature')

 
         

p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density")
p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature")
p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity")

 
         

par1.set_ylim(0,4)
par2.set_ylim(1,60)

 
         

host.legend()
#軸名稱,刻度值的顏色
host.axis['left'].label.set_color(p1.get_color())
par1.axis['right'].label.set_color(p2.get_color())
par2.axis['right2'].label.set_color(p3.get_color())
par2.axis['right2'].major_ticklabels.set_color(p3.get_color()) #刻度值顏色
par2.axis['right2'].set_axisline_style('-|>',size=1.5) #軸的形狀色
par2.axis['right2'].line.set_color(p3.get_color()) #軸的顏色

結果圖是這樣:

 

嘗試引入浮動坐標軸來實現多軸,但貌似浮動的縱軸如果在坐標邊界右邊就不能顯示出來了,

update: 浮動軸應該是只能在原坐標內顯示,要增加縱軸,像matplab中plotyyy函數那樣的縱軸要用固定軸,與浮動軸對應函數是ax.new_fixed_axis(location, offset)

代碼如下:

import mpl_toolkits.axisartist as AA
import matplotlib.pyplot as plt
%matplotlib inline
fig = plt.figure(1) #定義figure,(1)中的1是什么
ax = AA.Axes(fig, [0, 0, 0.9, 0.9])  #用[left, bottom, weight, height]的方式定義axes,0 <= l,b,w,h <= 1
fig.add_axes(ax)

#用Subplot的方式定義
ax1 = AA.Subplot(fig,211)
fig.add_axes(ax1)

#控制,t,b,r,l軸的顯示與否
ax.axis["right"].set_visible(False)
ax.axis["top"].set_visible(False)
ax1.axis['bottom'].set_visible(False)
ax1.axis['left'].set_visible(False)

#浮動軸,nth_coord=0是橫軸,=1是縱軸,value是交叉點
ax.axis['x=0.5'] = ax.new_floating_axis(nth_coord=1, value=0.5)
ax.axis['x=0.5'].set_axisline_style('->', size=1.5)  #坐標帶箭頭

#增加y軸,用new_fixed_axis(location, offset(右多少,上多少))
ax.axis['right2'] = ax.new_fixed_axis(loc='right',
offset=(50,0))

結果如下

 

 

 

 

 

試驗過程中發現一隱藏功能

jupyter notebook 碼如下:

%matplotlib inline

import numpy as np import matplotlib.pyplot as plt fig = plt.figure() t = np.arange(0.0, 1.0, 0.01) s = np.sin(2 * np.pi * t) c = np.cos(2 * np.pi * t) ax1 = fig.add_axes([0, 0, 0.8, 0.5]) line1, = ax1.plot(t, s, color='blue', lw=2) ax2 = fig.add_axes([0, 0, 0.8, 0.5]) line2, = ax2.plot(t, c, color='blue', lw=2) plt.show()

執行后跳出一提醒:

X:\anaconda3\lib\site-packages\matplotlib\cbook\deprecation.py:106: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a 
previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this
warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance. warnings.warn(message, mplDeprecation, stacklevel=1)
圖的效果是


因為參數一樣,把兩圖給合並顯示了,如果 ax2 = fig.add_axes([0, 0, 0.8, 0.5])中的l,b,w,h有一個不一樣,后定義的直接遮蓋前面定義,或加上去的axes


免責聲明!

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



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