matplotlibでグラフ作成(2軸グラフ)

x軸は時間で共通,y軸を流量と標高とした2軸グラフを作成します.

報告書に載せることを意識して,関連情報の描画まで行っています.

この作図でのテクニックとしては,線種を変えること,2軸グラフの凡例を1つのボックスに収めることの2点でしょうか.

とりあえず描く

データは,numpyで読み込み,左縦軸を流量,右縦軸を標高に設定します.

配列は,ti:時間,EL:水位標高,Qi:流入量,Qo:流出量を意味します.

2軸グラフなので,時間と流量の関係を描画後,twinxを入れて時間と水位標高の関係を描画します.

入力データは以下のような形式のものです.

    i   iUD       time         EL          EL-elv             VOL            q_in           q_out
    0     0      0.000     64.000    0.000000e+00    1.154000e+06    0.000000e+00    0.000000e+00
    1     1      1.000     64.681   -8.438230e-04    1.231048e+06    6.300000e+01    2.019536e+01
    2     1      2.000     65.836   -1.188468e-04    1.359809e+06    1.270000e+02    9.827084e+01
    3     1      3.000     66.558   -7.335385e-04    1.457899e+06    1.900000e+02    1.642349e+02

    .............................
In [1]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    fig=plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,lw=2.0,label='Q (outflow)')

    plt.twinx()
    plt.plot(ti,EL,lw=2.0,label='Water Level')

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)

凡例を表示

凡例をいれないとどれがどれだかわからない.

legendを2箇所に入れてみたけど重なってしまっています.

In [2]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    fig=plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,lw=2.0,label='Q (outflow)')
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)

    plt.twinx()
    plt.plot(ti,EL,lw=2.0,label='Water Level')
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)

そこで,twinxの前にlegendを入れますが,1つのボックスの中に3つの凡例を表示するため,水位標高表示のためのダミーを配置します.

3種類の凡例が1つのボックス内に表示されましたが,水位標高の凡例の表示色が,実際のプロットとあっていません.

In [3]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    fig=plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,lw=2.0,label='Q (outflow)')
    plt.plot([0],[0],lw=2.0,label='Water Level') #Dummy for legend
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)

    plt.twinx()
    plt.plot(ti,EL,lw=2.0,label='Water Level')

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)

線種を変える

そこで,ここでは線色を変えるのではなく,線種を変えることにより,3つのデータを示すことにします.

線種の指定は,以下を参照しました.

http://matplotlib.org/examples/lines_bars_and_markers/line_demo_dash_control.html

http://stackoverflow.com/questions/32446827/set-the-space-size-of-matplotlibs-linestyle-dashed

linestyle (ls)に dashed を指定し,dashes=[a, b, ...] で線描画のオン・オフを指定します.

In [4]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    fig=plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,color='#000000',ls='dashed',dashes=[3,1],lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,color='#000000',ls='dashed',dashes=[4,2,1,2],lw=2.0,label='Q (outflow)')
    plt.plot([0],[0],color='#000000',lw=2.0,label='Water Level') #Dummy for legend
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)

    plt.twinx()
    plt.plot(ti,EL,color='#000000',lw=2.0,label='Water Level')

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)

軸の調整

かっこよく行きました.あとは軸の調整を行います.

  • xlim, ylim : 軸の範囲設定(上限・下限)
  • xlabel, ylabel : 軸名ラベル
  • xticks, yticks : 軸数値
  • grid : グリッドの表示
In [8]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    xmin=0.0;xmax=132.0
    qmin=0.0;qmax=5000.0
    hmin=60.0;hmax=110.0

    fig=plt.figure()
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,color='#000000',ls='dashed',dashes=[3,1],lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,color='#000000',ls='dashed',dashes=[4,2,1,2],lw=2.0,label='Q (outflow)')
    plt.plot([0],[0],color='#000000',lw=2.0,label='Water Level') #Dummy for legend
    plt.xlim([xmin,xmax])
    plt.ylim([qmin,qmax])
    plt.xlabel('Time (hour)')
    plt.ylabel('Discharge (m$^3$/s)')
    plt.xticks(np.arange(xmin,xmax+12,12))
    plt.yticks(np.arange(qmin,qmax+1000,1000))
    plt.grid(color='#777777',linestyle='solid')
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)

    plt.twinx()
    plt.plot(ti,EL,color='#000000',lw=2.0,label='Water Level')
    plt.xlim([xmin,xmax])
    plt.ylim([hmin,hmax])
    plt.yticks(np.arange(hmin,hmax+5,5))
    plt.ylabel('Water Level (EL.m)')

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)

関連情報の表示

最後に関連情報を追加します.ここでは,以下の情報を追加表示しています.

  • inflow, outflow の最大値
  • 水位標高の最大値
  • トンネルのインバートと天端(クラウン)の位置(青線と青文字)
  • トンネルの内径と本数(左上:D7.0m x 2)

また図の表示サイズを fig=plt.figure(figsize=(8,5)) により少し大きくします.

In [13]:
import numpy as np
import matplotlib.pyplot as plt

def DRAWFIG(fnameR):
    data=np.loadtxt(fnameR,skiprows=1,usecols=(2,3,6,7))
    ti=data[:,0]
    EL=data[:,1]
    Qi=data[:,2]
    Qo=data[:,3]

    n1=np.argmax(Qi)
    n2=np.argmax(Qo)
    n3=np.argmax(EL)

    xmin=0.0;xmax=132.0
    qmin=0.0;qmax=5000.0
    hmin=60.0;hmax=110.0

    fig=plt.figure(figsize=(8,5))
    ax = fig.add_subplot(111)
    plt.plot(ti,Qi,color='#000000',ls='dashed',dashes=[3,1],lw=2.0,label='Q (inflow)')
    plt.plot(ti,Qo,color='#000000',ls='dashed',dashes=[4,2,1,2],lw=2.0,label='Q (outflow)')
    plt.plot([0],[0],color='#000000',lw=2.0,label='Water Level') #Dummy for legend
    plt.xlim([xmin,xmax])
    plt.ylim([qmin,qmax])
    plt.xlabel('Time (hour)')
    plt.ylabel('Discharge (m$^3$/s)')
    plt.xticks(np.arange(xmin,xmax+12,12))
    plt.yticks(np.arange(qmin,qmax+1000,1000))
    plt.grid(color='#777777',linestyle='solid')
    plt.legend(shadow=True,loc='upper right',handlelength=3,fontsize=10)
    # Additional information
    plt.text(ti[n1],Qi[n1],'max:%.0f'%max(Qi),fontsize=10,color='#000000',ha='left',va='bottom')
    plt.text(ti[n2],Qo[n2],'max:%.0f'%max(Qo),fontsize=10,color='#000000',ha='left',va='bottom')

    plt.twinx()
    plt.plot(ti,EL,color='#000000',lw=2.0,label='Water Level')
    plt.xlim([xmin,xmax])
    plt.ylim([hmin,hmax])
    plt.yticks(np.arange(hmin,hmax+5,5))
    plt.ylabel('Water Level (EL.m)')
    # Additional information
    plt.text(ti[n3],EL[n3],'ELmax:%.3f'%max(EL),fontsize=10,color='#000000',ha='left',va='bottom')
    crh=64.0+float(fnameR[4:6])
    sch='{0:4.3f}'.format(crh)
    strd='D{0:.1f}m x 2'.format(float(fnameR[4:6]))
    plt.hlines([64.0],xmin,xmax,color='#0000ff',lw=1.0,linestyle='solid') # Line of Tunnel invert
    plt.hlines([crh],xmin,xmax,color='#0000ff',lw=1.0,linestyle='solid') # Line of Tunnel crown
    plt.text(xmax-5,64.0,'Tunnel InvertL:EL.64.0',fontsize=10,color='#0000ff',ha='right',va='top')
    plt.text(xmax-5,crh,'Tunnel Crown:EL.'+sch,fontsize=10,color='#0000ff',ha='right',va='bottom')
    plt.text(0.03, 0.95, strd, transform=ax.transAxes,fontsize=16,ha='left', va='top') # Tunnel diameter

# Main routine
fnameR='out_07flood_20.txt'
DRAWFIG(fnameR)
In [ ]: