SBI証券の資産推移をグラフで表示する方法を考えてみる日記【その16】

さて、前回はmatplotlibで積み上げグラフと折れ線グラフの複合グラフを作るところまで行きました。その後、データラベルを表示しようとしたのですが、結構面倒そうなことがわかりました。(DataFrameをfor文で回して、1つずつデータラベルを表示する位置を指定してデータラベルを表示する必要がある)

ちょっと調べて見たところplotlyという使い勝手の良さそうなライブラリがあるようなのでこれを試してみたいと思います。

とりあえずこれだけのコードでグラフはできるようです。

import plotly
import plotly.graph_objs as go
def draw_portfolio_graph_plotly():
   df_master = pd.read_csv('/content/drive/My Drive/資産管理/sbisec/PortFolioMaster.csv')
   df = pd.pivot_table(df_master, index='年月日', values=['評価額','損益','取得額'], aggfunc='sum')

   #グラフのデータを設定する
   data = [
       go.Bar(x=df.index, y=df['取得額'], name='取得額'),      #棒グラフ 取得額の設定
       go.Bar(x=df.index, y=df['損益'], name='損益'),          #棒グラフ 損益の設定
       go.Scatter(x=df.index, y=df['評価額'], name='評価額'), #折れ線グラフ 評価額の設定
   ]

   fig = go.Figure(data=data) #グラフデータをグラフオブジェクトに渡す
   fig.update_layout(barmode='stack') #棒グラフを積み上げにする
   fig.show() #グラフを表示する

draw_portfolio_graph_plotly()

直感的にコードを見て何をやっているのかわかりやすいです。実行してみます。

スクリーンショット 2020-10-01 0.46.19

おお、X軸の日付はデータがない日は自動で間隔が空いています。自動で日付として認識して調整してくれているということですね。すごいです。

マウスカーソルを合わせると動的にデータの内容が表示されます。すごいです。

右上のアイコンをクリックすると、選択した部分を拡大したり、パンしたりできます。すごいです。

すごく高機能なので既にかなり満足してしまったのですが、第1回でイメージしていたようにデータラベルを表示してみたいと思います。

公式のリファレンスを見るとgo.Barにtextを渡してあげれば良いみたいです。data部分のコードを書き換えてみます。

    data = [
       go.Bar(x=df.index, y=df['取得額'], name='取得額', text=df['取得額']),      #棒グラフ 取得額の設定
       go.Bar(x=df.index, y=df['損益'], name='損益', text=df['損益']),          #棒グラフ 損益の設定
       go.Scatter(x=df.index, y=df['評価額'], name='評価額', text=df['評価額']), #折れ線グラフ 評価額の設定
   ]

んー、何も表示されません。どうやらtextpositionも設定しないとダメな様です。

   #グラフのデータを設定する
   data = [
       go.Bar(x=df.index, y=df['取得額'], name='取得額', text=df['取得額'], textposition='auto'),      #棒グラフ 取得額の設定
       go.Bar(x=df.index, y=df['損益'], name='損益', text=df['損益'], textposition='auto'),          #棒グラフ 損益の設定
       go.Scatter(x=df.index, y=df['評価額'], name='評価額', text=df['評価額'], textposition='auto'), #折れ線グラフ 評価額の設定
   ]
ValueError: 
   Invalid value of type 'builtins.str' received for the 'textposition' property of scatter
       Received value: 'auto'

   The 'textposition' property is an enumeration that may be specified as:
     - One of the following enumeration values:
           ['top left', 'top center', 'top right', 'middle left',
           'middle center', 'middle right', 'bottom left', 'bottom
           center', 'bottom right']
     - A tuple, list, or one-dimensional numpy array of the above

Scatterではtextposition='auto'は使えないと怒られました。グラフの種類によってtextpositionに設定できる値が異なるようです。エラーメッセージに出ている'top center'に設定して実行してみます。

スクリーンショット 2020-10-01 2.32.59

棒グラフの方はデータラベルが表示されましたが、折れ線グラフはデータラベルが表示されないですね・・・。しかし、ちゃんと棒グラフの中にデータラベルが収まる様に自動調整してくれているのがすごいです。

とりあえず、見やすくするために小数点以下を非表示にして、3桁毎にカンマ区切りを入れたいです。

公式リファレンスを調べたところ、textのフォーマットはtexttemplateで設定できるようです。フォーマットはd3-formatの構文で指定する様です。d3-format・・・。なんでしょう。初めて聞きました。

調べてみたところ、3桁のカンマ区切りはシンプルに「,」を入れれば良いようです。"4.2"は「.1」で"4"を返すというサンプルがあったのでこの2つを組み合わせれば良さそうです。

    data = [
       go.Bar(x=df.index, y=df['取得額'], name='取得額', text=df['取得額'], textposition='auto', texttemplate='%{text:,.1}'),      #棒グラフ 取得額の設定
       go.Bar(x=df.index, y=df['損益'], name='損益', text=df['取得額'], textposition='auto'),          #棒グラフ 損益の設定
       go.Scatter(x=df.index, y=df['評価額'], name='評価額', text=df['取得額'], textposition='top center'), #折れ線グラフ 評価額の設定
   ]

実行してみます。

スクリーンショット 2020-10-01 2.34.50

3桁カンマ区切りになりましたが、小数点以下が出ずっぱりですね。調べてみると「.d」で10進数の整数に丸められるみたいなのですが、実行してもピクリとも変化しません。うーん、困りました。

とりあえず手当たり次第に試してみて結局「,.0f」で上手くいきました。ここで1時間くらいハマりました。なんで上手くいったのか理解できていませんが、深追いはしないでおきます。

コードは以下の様になりました。

    data = [
       go.Bar(x=df.index, y=df['取得額'], name='取得額', text=df['取得額'], textposition='auto', texttemplate='%{text:,.0f}'),      #棒グラフ 取得額の設定
       go.Bar(x=df.index, y=df['損益'], name='損益', text=df['取得額'], textposition='auto', texttemplate='%{text:,.0f}'),          #棒グラフ 損益の設定
       go.Scatter(x=df.index, y=df['評価額'], name='評価額', text=df['取得額'], textposition='top center'), #折れ線グラフ 評価額の設定
   ]

実行してみます。

スクリーンショット 2020-10-01 2.38.05

はい、3桁カンマ区切りの、小数点以下非表示になりました。

かなりハマって時間を使ってしまったので今回はこの辺にしておきます。

次回は、折れ線グラフのデータラベル表示にチャレンジしたいと思います。

参考にさせて頂いた尊いサイト

Pythonでお洒落なグラフを描画!3Dやアニメーションによる可視化の基本

[Python] Plotlyでぐりぐり動かせるグラフを作る

Plotly 棒状図と折り線の複合チャート

D3.jsのformatを整理

d3.formatについて




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