見出し画像

Python OpenPyXLで【第2軸付き】グラフ作成に成功!?

1.はじめに

   1年位前にFXを始めて、過去の履歴からデータ
   を分析しようとCSVファイルをエクセルで
   開こうとしたのですが、約571万行あったため
   開くことができませんでした。
   エクセルは約105万行が上限でした。
   そこで、Pythonで範囲を指定しデータ
   を抽出するプログラムを作成しました。

   そのデータを分析するのにグラフも描く
   わけですが、ここで気づきました。
   あれっ、データ抽出と同時にグラフも描けば
   いいのでは?と。   

   ネットでPython+グラフを検索しますと、
   pandasや、openpyxlがよく見つかります。
   エクセルと互換性があってほしいと思い、
   xlwingsも調べました。  
   エクセルとの相性が良いとのことですが、
   グラフをどう描くのかよく分かりません
   でした。

   そして、最終的にはopenpyxlでグラフを描く
   ことにしました。
   更に大事なことは、「第2軸付きグラフを描く
   こと」
です。
   情報が非常に少なかったのですが、なんとか
   作成することに成功しました。

   そこで、こんなに情報が少ないと他にも苦労
   されている方がいるのでは?と思い、ここに
   記録することにしました。

   ド素人なので、全体の作りはよくありません 
   が、自分が苦労したことや、気になることも
   記録してみました。
   また、自分用の説明書でもあるため変な表現
   になっているところもあるかも知れません。

   お役に立てましたら幸いです。


2.第2軸付きグラフの概要

   下の画像は、練習で使う「灯油価格」という
   データで、目標とする完成形のグラフを
   エクセルで描きました。

   表の部分をPythonに読み込んで処理して
   表の下に同じような、「第2軸付きグラフ」
   描いてみます。 

   以下でソースコード公開とエクセル表を
   ダウンロードできるようにします。
     

エクセルで作成した練習用表と作成目標グラフ

   ここでのポイントは、Y第1軸とY第2軸を別々
   に作成して合成する
というところです。

練習用表にてグラフ作成範囲を示している


3.ソースコードと練習用表(エクセル)

   私のPython環境
   ・Windows 10 Pro 64bit
   ・Python 3.8.16
   ・openpyxl 3.0.10
   ・ソースコードエディタ
    Visual Studio Code 1.75.1

import openpyxl
from openpyxl.chart import LineChart, BarChart, Reference, Series
from openpyxl.chart.axis import DateAxis

wb = openpyxl.load_workbook("kerosene.xlsx")  # 練習用表を開く

ws = wb['Sheet1']  # エクセルのシートを選択


# Y第1軸の棒グラフ作成

graph = openpyxl.chart.BarChart()  # 棒グラフ選択

graph.title  = "灯油価格"  # グラフのタイトル

graph.y_axis.title = "支払額(円)"  # Y第1軸のラベル名

graph.x_axis.title = "日付"  # X軸のラベル名

v = Reference(ws, min_col=2, min_row=4, max_col=2, max_row=12)  # Y第1軸の項目含むデータ(支払額)選択

graph.add_data(v, titles_from_data=True)  # Y第1軸のグラフ描きだし

h = Reference(ws, min_col=1, min_row=5, max_col=1, max_row=12) # X軸の項目含まないデータ(日付)選択

graph.set_categories(h)  # X軸のグラフ追加


# Y第2軸の折れ線グラフ作成

graph2 = openpyxl.chart.LineChart()  # 折れ線グラフ選択

graph2.y_axis.title = "単価(円)"  # Y第2軸のラベル名

graph2.y_axis.majorGridlines = None  # Y第2軸のグリット線を表示しない

v2 = Reference(ws, min_col=4, min_row=4, max_col=4, max_row=12)  # Y第2軸の項目含むデータ(単価)選択

graph2.add_data(v2, titles_from_data=True)  # Y第2軸のグラフ描きだし

graph2.series[0].marker.symbol = 'circle'  # 折れ線グラフに丸マーカー設定

h2 = Reference(ws, min_col=4, min_row=5, max_col=4, max_row=12) # X軸の項目含まないデータ(日付)選択


# Y第2軸形成

graph2.y_axis.axId = 200  # Y第2軸の形成に関わっているようで実行しないとY第2軸が形成されない

graph2.y_axis.crosses = 'max'  # Y第2軸を右に移動する命令らしい


# 別々に作成したY第1軸とY第2軸を1つにする

graph += graph2  # 支払額のY第1軸と単価のY第2軸のデータを合成する


# 出力

ws.add_chart(graph, 'A15')  # 読み込んだ練習表の下セルA15にグラフを貼りつける

wb.save("kerosene_2ndg.xlsx")  # エクセルを別名で保存

wb.close()  # エクセルを閉じる命名

   実行されたい方は、上記ソースコードと
   練習用表 kerosene.xlsx をご自由にお使い
   ください。
   ソースコードファイルとkerosene.xlsx を
   同じフォルダに入れて実行すればグラフが
   描けます。
   尚、エクセルファイルは、ソースネクスト社  
   のZERO スーパーセキュリティソフトで
   ウイルスチェックし問題なしとの結果です。

   ソースコードの構成は、
   ①練習用表(エクセル)の読み込み
   ②Y第1軸の棒グラフ作成(日付のX軸含む)
   ③Y第2軸の折れ線グラフ作成(日付のX軸含む)
   ④Y第2軸形成
   ⑤Y第1軸グラフとY第2軸グラフを合成する
   ⑥エクセルへ出力する

   といった内容です。

   各所に処理内容をコメントで記載しました
   のでご参考にしてください。

   尚、コード組み立てや慣習等よく分かって
   おりませんので、その点は大目に見て
   ください。


4.実行結果

   上記4.のデータで実行しましたら、下記画像
   の結果が得られました。
   グラフのY第2軸を形成し、セルA15にグラフ 
   を貼り付けることができました。
 

プログラムを実行した結果のエクセル
目標グラフとプログラム実行結果グラフの比較

   気になる点
    ①凡例が右にある
     配置場所はlegendという命令で設定
     できるようですが今回は設定して
     いません。

    ②グラフの色
     設定はしていませんので自動で色が
     つけられたようです。
     ちなみに、エクセルで作成した目標
     グラフの色も設定しておりません。

    ③その他の設定
     今回は、折れ線のマーカー(丸)は
     設定しましたが、その他の設定
     例えば、線の種類や太さなどは
     設定していません。  


5.気になる部分のソースコードを深掘り

   Y第2軸を形成するにあたり4.でご紹介しまし 
   たソースコード構成の④と⑤が肝となりそう
   です。
   ですので、実行させなかったり値を変えたり
   してどのようになるか実験してみます。

    【graph2.y_axis.axId = 200
    # Y第2軸の形成に関わっているようで実行
      しないとY第2軸が形成されない】

    のコードを実行するしないの比較結果
    
です。

ソースコードの一部を実行するしない比較

    次に、axId=0,10,200(基準),1000で比較
    しましたが、違いは分かりませんでした。
    なぜか、axId=10はグラフが描けないエラー
    となりました。

    axIdについて調べたのですがよく分かりま
    せんでした。

    ですので、ネットでみつけたaxId=200
    そのままにしています。

ソースコードの一部の値を替えて比較

    つづきまして、
    【graph2.y_axis.crosses = 'max'
    # Y第2軸を右に移動する命令らしい】
    のコードを実行するしないの比較結果
    
です。

ソースコードの一部を実行するしない比較

    graph2.y_axis.crosses = 'max'
   
 これを見て、minとかmidあるのかな?
    と思い試してみました。
    Y第2軸が左に来てしまいました。
    何が起こったかは分かりません。

ソースコードの一部の値を替えて比較

    つづきまして、
    【graph += graph2  # 支払額のY第1軸と
    単価のY第2軸のデータを合成する】
    
コードを実行するしないの比較結果
    
です。

ソースコードの一部を実行するしない比較

    ここで気になってしまいました。
    単純ですが、graph += graph2
    graph2 += graph
と左右を入れ
    替えた場合どうなるのか比較
    したいと思います。 
    ※graphはY第1軸、graph2はY第2軸

    Y第1軸グラフが上書き状態となった
    ようです。

ソースコードの左右辺入替ありなし比較

6.最後に

   最後までご覧いただきありがとう
   ございました。
   自分用の説明書でもあるためご覧になった
   方には違和感のある表現もあったかと思い
   ますが、ご参考になることを願っています。


この記事が気に入ったらサポートをしてみませんか?