こんにちは、hokkyokunです。
VBA学習者向けに
「Pythonいいって聞いたけど実際どうなの?」
という疑問に具体的な目的を処理するコードで比べてみます。
具体的な目的の処理
具体的な目的は以下です。
このVOOの株価データから
月利(月初から月末にかけての値動きの割合)を計算して可視化する。
が大きな目的です。
これを達成するために以下の細かな目標に分けました。
それぞれ記事にしています。
- 2次元データを扱うオブジェクトを取得
- 2022年3月~2023年2月までの絞り込み
- 月末月初の日付を取得
- 月末月初の値と各月の月利(月当たりの価格変動)
を計算して表で取得する - 取得したデータで簡単なグラフを作成する
↑今回処理するのはこれ!
前回は④の処理を
PythonとVBAでそれぞれ書いてみました。
正直、Pythonの方が楽です!!
一方で⑤グラフ化は今までとは様子が違います。
今回は⑤得られた表データをグラフにして可視化します。
VBAでのコード
Sub グラフ()
Dim table As ListObject 'テーブル変数
Dim leftPnt As Integer 'グラフの作成位置取得変数
'表をテーブル化して取得
'既にテーブル化している場合は、再度テーブル化するとエラーが出るので回避
With ThisWorkbook.Worksheets(1)
Set table = .Cells(1, 1).ListObject
If table Is Nothing Then
Set table = .ListObjects.Add(xlSrcRange, .Cells(1, 1).CurrentRegion, , xlYes)
End If
End With
'テーブルの最右列の二つ隣のセルの左上の端っこのポイントを取得
leftPnt = table.ListColumns(table.ListColumns.Count).Range(1).Offset(, 2).Left
'ActiveSheet.ChartObjects.Add(leftPnt, 20, 400, 300)でChartObjectsを返してくれるので、
'その後ろにChartをつける。
'ほとんどがChartオブジェクトをいじることになるので、Withでつなげる。
With ActiveSheet.ChartObjects.Add(leftPnt, 20, 400, 300).Chart
.SetSourceData table.Range 'グラフの範囲をざっくりとる(いきなりちゃんととってももちろんいいです)
.ChartType = xlColumnClustered 'グラフの種類を決める
.Axes(xlCategory).CategoryType = xlCategoryScale 'X軸を調整
.ChartColor = 14
'グラフにするデータをブラッシュアップする(必要なとこだけとる)
.SetSourceData Union(table.ListColumns("月初日").Range, table.ListColumns("月利").Range)
.ChartTitle.Text = "VOO月利" 'グラフのタイトルを変える
.Legend.Delete '凡例を消す
End With
End Sub
グラフ作成は久しぶりでほとんど忘れていたので
自分で書いた記事を見返して作成しました。
ほとんど自分で書いた記事のコードをコピペしただけです。
今回のグラフにはいらない部分を少し削り、必要な記述を一行だけ追加しました(後述)
こちらに記事があります。
この記事で公開しているコードをコピペすれば大体のグラフはできると思います。
23行目に「.Axes(xlCategory).CategoryType = xlCategoryScale」を追加しています
今回は棒グラフを作成していますが、値がプラスだったりマイナスだったりしているため
X軸を何度もまたぐようなグラフになっています。
おそらくそういったグラフは
棒グラフの棒を線のように細く記述するよう自動的に調整されると思われます。
これだと見栄えが悪かったので、
上記のコードを追加して自分好みのグラフに調整しました。
VBAもPythonもグラフ化は結構細かい調整が必要となるため
すべてのメソッド、引数を覚えることは不可能だし、無意味です。
VBAに関しては「マクロの記録」という強力なツールが備わっているので
こちらの記事のコードをひな形に、マクロの記録でグラフの調整方法を調べてコードを記述するが効率的です。
Pythonでのコード
今回も数行(最後の3行)で記述が終わったので
最初からすべて載せておきます。
############前回と同じ#########################################################
import pandas as pd
import datetime as dt
#ファイルを開いてデータフレームを取得
df=pd.read_csv("./VOO.csv")
#日付のデータ型を日付型に変える
df["Date"]=pd.to_datetime(df["Date"],format="%Y-%m-%d")
#日付をインデックスにして検索や絞り込みをしやすくする
df=df.set_index("Date",drop=False)
#日付で絞る
df=df[dt.datetime(2022,3,8):dt.datetime(2023,2,28)]
#データフレームを月毎に区分けして月初日、月末日およびそれぞれの値(Adj Close列の値)を
#新しいデータフレーム(df_result)に格納
df_result=pd.DataFrame()
df_result["月初日"]=df.resample("M").first()["Date"].tolist()
df_result["月末日"]=df.resample("M").last()["Date"].tolist()
df_result["月初の値"]=df.resample("M").first()["Adj Close"].tolist()
df_result["月末の値"]=df.resample("M").last()["Adj Close"].tolist()
df_result["月利"]=(df_result["月初の値"]-df_result["月末の値"])/df_result["月末の値"]*100
###############################################################################
df_result["月初日"]=df_result["月初日"].dt.strftime("%Y/%m/%d")
df_result=df_result.set_index("月初日")
df_result["月利"].plot.bar()
軸ラベルの調整とか、日本語表記可能にする記述など
設定は色々必要ですが、最低限のグラフ化であればこれだけで十分記述できました。
コーディングの違いは?
- 表をグラフ化する工程数
VBAは19行
Pythonは3行 - グラフ化は細かい設定が無数にあり、覚えることは不可能
また、自動調整のグラフはあまり見栄えが良くないことが多い
→マクロの記述が使えるVBAが意外と良い!
Pythonの方が簡単に記述はできました。
しかし、グラフ化処理は自動設定の場合、見栄えが良くないことが多いです。
これは経験上、VBAでもPythonでも同じです。
グラフ化の記述は結構面倒なうえ、メソッドやその引数を覚えることは不可能なので
グラフをさわりながら調整方法を調べていくことが現実的です。
Pythonの場合はseaborn(シーボーン)というきれいなグラフを作るライブラリがあるので
ちょっと手の込んだグラフはこちらを使うと比較的きれいなグラフが書けます
(経験上それでも調整は必要ですが…)
VBAとPythonどちらを使えばよいか?
個人的にはグラフはVBAの方がやりやすいかなと思います。
- VBAは「マクロの記述」でコードを調べられる
- エクセル上にグラフを作成した後は
マウス、キー入力などで調整やデータの修正などが簡単
マクロの記述関連は上記で散々言ったので割愛するとして
個人的にはデータの加工はPythonを使い、
グラフ化はVBAで行ってもいいかなと思います。
ただ、一連の作業をワンクリックでやりたいので
頑張ってPythonでグラフ作成を勉強していますが。。。
VBAのグラフ化のテンプレートはこちらにあります。
これをひな形に「マクロの記述」でコードを調べれば大体のグラフは事足りるんじゃないかなと思います。
次回
以上で当初の目的であった
VOOの株価データから
月利(月初から月末にかけての値動きの割合)を計算して可視化する。
ができるようになりました。
最後に一連のコードを全てつなげて
VBAとPythonでどれくらいコード量が異なるのか
実際どちらをどう使っていきばいいのか考察していきたいと思います。