Pythonで大量のグラフを一括で作成する

1.はじめに

今回はPythonを使って大量のグラフを一括で作成していきます。比較的によく使われる機能だと思うので、参考になれば幸いです。

グラフ作成といえばExcelなのですが、一括作成に関しましてはPythonのほうが圧倒的に便利です。その理由としまして、Excelは基本機能でグラフを一括で作成することができず、マクロを組む必要があります。しかし、マクロを組んだとしてもExcel自体の動作が重くなってしまい、強制終了してしまう場合も多々あります。PCのスペックによりますが、体感20個くらいが限界かなと思います。その点、Pythonでは100個でも問題なく作成できます。ただ、Pythonにも難しいところがあり、データの入れ替え、グラフの種類、色や配置などのデザインなどは設定が煩雑でExcelのほうが圧倒的に使い易いです。
このあたりを踏まえて、目的に応じた手段を選んでいただければと思います。

2.データの準備

まず、今回どのような形式でグラフを作成するかといいますと「大量のデータから一部の区間を抜粋したグラフ」を大量に作成していきたいと思います。ですので必要なデータは、

  • グラフで表したいデータのCSV
  • 抽出する区間とタイトルのCSV

になります。今回の例では、潮位観測所(伊勢湾、尾鷲、潮岬)の2007年~2022年の20分ごとの潮位データが「グラフで表したいデータ」となり、期間内で起きた擾乱を「抽出する区間とタイトル」としています。下の画像を参考にしてください。

  • 番号:整理番号(3が始めになっている意味は特にないです)
  • 日時:日付(CSVなのでシリアル値になっています)
  • 伊勢湾~潮岬:それぞれの潮位の値
  • 期間番号:整理番号
  • 始点、終点:それぞれの期間の始点と終点の番号(グラフ用データの「番号」に対応しています)
  • タイトル:グラフのタイトル(最終的にグラフに表示されます)

3.グラフ作成のコード

下記にグラフ作成のコードを記載いたします。データ参照箇所や列の指定などは適宜調整してください。

import csv
import pandas as pd
import matplotlib.pyplot as plt
import datetime
from matplotlib.dates import DateFormatter

#基本はこっち
%matplotlib inline

#出力されるグラフが真っ白な場合こっちを使う
#%matplotlib notebook 

path_dcsv = r'【グラフ用データ.csv保存先のパス】\グラフ用データ.csv'
df_dcsv = pd.read_csv(path_dcsv,encoding = "shift-jis")
#シリアル値を日付へ変更
df_dcsv2 = df_dcsv.copy()
df_dcsv2['日時'] = pd.to_datetime(df_dcsv2['日時'], unit='D', origin='1899/12/30')

path_tcsv = r'【グラフタイトル.csv保存先のパス】\グラフタイトル.csv'
df_tcsv = pd.read_csv(path_tcsv,encoding = "shift-jis")

#保存先のパスを指定
savegraph_path = r'【出力したい保存先のパス】'

#整理番号を参照して作成するグラフの個数を判別
df_tcsv_i = df_tcsv.tail(1)
i = df_tcsv_i.iloc[0, 0]
i = i+1

for count in range(1,i):
    df_tcsv_g = df_tcsv[df_tcsv["期間番号"] == count]
    B_No = df_tcsv_g.iloc[0, 1]
    E_No = df_tcsv_g.iloc[0, 2]
    title = df_tcsv_g.iloc[0, 3]

    data_x = df_dcsv2.iloc[B_No:E_No, 1]
    idata_y = df_dcsv2.iloc[B_No:E_No, 2]
    odata_y = df_dcsv2.iloc[B_No:E_No, 3]
    sdata_y = df_dcsv2.iloc[B_No:E_No, 4]

    fig, ax = plt.subplots()

    ax.set_ylabel('m')
    ax.set_title(title)

    ax.plot(data_x,idata_y,color="blue", label="isewan")
    ax.plot(data_x,odata_y,color="green", label="owase")
    ax.plot(data_x,sdata_y,color="red", label="sionomisaki")
    ax.legend(loc=0) 
    
    plt.annotate(f'Max: {idata_y.max()}', xy=(data_x[idata_y.idxmax()], idata_y.max()), xytext=(10, -10), textcoords='offset points', arrowprops=dict(arrowstyle='->', color="blue"), color="deepskyblue")
    plt.annotate(f'Max: {odata_y.max()}', xy=(data_x[odata_y.idxmax()], odata_y.max()), xytext=(10, -10), textcoords='offset points', arrowprops=dict(arrowstyle='->', color="green"), color="springgreen")
    plt.annotate(f'Max: {sdata_y.max()}', xy=(data_x[sdata_y.idxmax()], sdata_y.max()), xytext=(10, -10), textcoords='offset points', arrowprops=dict(arrowstyle='->', color="red"), color="hotpink")
    
    date_fmt = DateFormatter('%Y/%m/%d')
    ax.xaxis.set_major_formatter(date_fmt)
    plt.xticks(rotation=45)#x軸のラベルのを45°傾ける

    plt.show()
    graphname = savegraph_path + "\\" + title + ".png"
    plt.savefig ( graphname,bbox_inches='tight' )

出力されたものは以下になります。

今回の例では、92個のグラフを10秒ほどで作成できました。

4.補足

グラフを出力する際に、Python上ではグラフが表示されるのですが、出力されたグラフが真っ白の場合があります。明確な原因はわからないのですが、解決方法としては下記のコードを部分を変更することで治る場合があります。

#基本はこっち
%matplotlib inline

#出力されるグラフが真っ白な場合こっちを使う
%matplotlib notebook 

出力するデータの形式ですが、下記のものに対応しています。

  • emf
  • eps
  • jpeg
  • jpg
  • pdf
  • png
  • ps
  • raw
  • rgba
  • svg
  • svgz
  • tif
  • tiff

コードの下記の箇所を変更することで、出力フォーマットを変更できます。

#「.png」を出力したいフォーマットに変更
    graphname = savegraph_path + "\\" + title + ".png"

以上になります。

コメント