damyarou

python, GMT などのプログラム

matplotlib 時系列グラフの軸設定

記事の最後に行く

はじめに

時系列グラフの事例を紹介する。 このグラフ作成のポイントは、時間軸の設定方法である。

この記事はQiitaに投稿した以下の記事を再アレンジしたものである。

出力画像

f:id:damyarou:20190505090405j:plain

プログラム

データ入力

このプログラムでは2つのファイルを読み込んでいる。

ファイル:xls_calvert.xlsx

f:id:damyarou:20190505090427p:plain

1つ目のデータファイルは、エクセルファイルに、日(dd)、月(mm)、年(yy)、流量(Q)という順序にデータが格納されている。 これは、自分で打ち込んだため、打ち込みやすいように、日・月・年のカラムを分離したためである。 一つのカラムに dd/mm/yy と入力するよりは、打ち込み効率は高い。

これをpandasで読み込むわけであるが、作図時の扱いを楽にするため、各カラムの文字列を連結して年月日を示すインデックスとしてデータフレームに格納する。

プロットデータを線で連結したくない場所には、データとしてnanを入れておけば、そこは線を結ばないよう自動調整してくれる。

    # discharge data input
    fnameR='xls_calvert.xlsx'
    df = pd.read_excel(fnameR,sheet_name='data')
    ss=[]
    for sd,sm,sy in zip(df['dd'],df['mm'],df['yy']):
        s1='{0:0>2d}'.format(sd)
        s2='{0:0>2d}'.format(sm)
        s3='{0:0>4d}'.format(sy)
        ss=ss+[s1+'/'+s2+'/'+s3]
    df.index=pd.to_datetime(ss, format='%d/%m/%Y')

ファイル:xls_v-notch.xlsx

f:id:damyarou:20190505090500p:plain

2つ目のデータファイルは、エクセル上のカラムで、A〜Nまでに格納されているが、今回使うのは、AとNだけであるので、データ読み込み時に、usecols=[0,13]を指定し、col=0をインデックスとしている。

    # reservoir water level input
    fnameR='xls_v-notch.xlsx'
    dfr = pd.read_excel(fnameR,usecols=[0,13],index_col=0)
    dfr.index = pd.to_datetime(dfr.index, format='%d/%m/%Y')

横軸設定

横軸の範囲を2015年3月1日から2019年3月31日に指定する。

    sxmin='2015-03-01'
    sxmax='2019-03-31'
    xmin = datetime.datetime.strptime(sxmin, '%Y-%m-%d')
    xmax = datetime.datetime.strptime(sxmax, '%Y-%m-%d')
    plt.xlim([xmin,xmax])

データプロット

2軸グラフとしているため、plt.twinx()の前後で、左縦軸プロット、右縦軸プロットを実施する。 プロットデータは、横軸をデータフレームのインデックス、縦軸をデータフレームのカラムとして行う。

# 左縦軸プロット
    df = pd.read_excel(fnameR,sheet_name='data')
    .....
    plt.twinx()
    .....
# 右縦軸プロット
    plt.plot(dfr.index,dfr['RWL'],'-',lw=2,color='#0000ff',label='RWL')

横軸(時間軸)目盛りの書式制御

プロット命令が終わったあとに、以下を挿入して横軸(時間軸)目盛りの出力を制御する。 この事例では、以下の設定を行っている。

  • 日付目盛り書式を「日ー月ー年」とし、月は英語短縮形とする。
  • 6ヶ月ピッチにグリッド線を入れる。( grid の指定は major のみ)
  • 1ヶ月ピッチで小さい目盛り線を入れる。
  • 日付を適当に自動で回転させる。
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%b-%Y'))
    plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=6))
    plt.gca().xaxis.set_minor_locator(mdates.MonthLocator(interval=1))
    plt.gcf().autofmt_xdate()

プログラム全文

# Time series drawing
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime
import matplotlib.dates as mdates


def inpdata():
    # discharge data input
    fnameR='xls_calvert.xlsx'
    df = pd.read_excel(fnameR,sheet_name='data')
    ss=[]
    for sd,sm,sy in zip(df['dd'],df['mm'],df['yy']):
        s1='{0:0>2d}'.format(sd)
        s2='{0:0>2d}'.format(sm)
        s3='{0:0>4d}'.format(sy)
        ss=ss+[s1+'/'+s2+'/'+s3]
    df.index=pd.to_datetime(ss, format='%d/%m/%Y')
    # reservoir water level input
    fnameR='xls_v-notch.xlsx'
    dfr = pd.read_excel(fnameR,usecols=[0,13],index_col=0)
    dfr.index = pd.to_datetime(dfr.index, format='%d/%m/%Y')
    return df,dfr
    
    
def drawfig(df,dfr):
    fsz=12
    plt.figure(figsize=(10,6),facecolor='w')
    plt.rcParams['font.size']=fsz
    sxmin='2015-03-01'
    sxmax='2019-03-31'
    xmin = datetime.datetime.strptime(sxmin, '%Y-%m-%d')
    xmax = datetime.datetime.strptime(sxmax, '%Y-%m-%d')
    plt.xlim([xmin,xmax])
    plt.ylim([0,500])
    plt.xlabel('Date')
    plt.ylabel('Discharge (Liter/min)')
    plt.grid(which='major',axis='both',color='#999999',linestyle='--')

    plt.plot(df.index,df['Q'],'-',color='#ff0000',label='Discharge')
    qs=165.0; spot='2016-05-31'
    dsp = datetime.datetime.strptime(spot, '%Y-%m-%d')
    plt.plot([dsp],[qs],'o',color='#ff0000')
    ss='31/05/2016\n{0:.0f}L/min'.format(qs)
    plt.text(dsp,qs-10,ss,va='top',ha='center',fontsize=fsz-2)
    plt.title('Discharge of Calvert at River Outlet Bay',loc='left',fontsize=fsz)
    plt.twinx()
    plt.ylim([65,90])
    plt.ylabel('Reservoir Water Level (EL.m)')
    plt.plot(dfr.index,dfr['RWL'],'-',lw=2,color='#0000ff',label='RWL')
    plt.plot([0],[0],'-',color='#ff0000',label='Discharge') # dummy for legend
    plt.legend(loc='lower right',fontsize=fsz,shadow=True)
    
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%d-%b-%Y'))
    plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=6))
    plt.gca().xaxis.set_minor_locator(mdates.MonthLocator(interval=1))
    plt.gcf().autofmt_xdate()

    fnameF='fig_calvert.jpg'
    plt.savefig(fnameF, dpi=100, bbox_inches="tight", pad_inches=0.1)
    plt.show()


def main():
    df,dfr=inpdata()
    drawfig(df,dfr)
    

#==============
# Execution
#==============
if __name__ == '__main__': main()

Thank you.

記事の先頭に行く