Plotlyでグループ化された積上げ棒グラフを作る方法

EIAの原油データをまとめている際にグループ化された積上げ棒グラフ(Grouped and Stacked Bar Chart)や積上げ面グラフ(Stacked Area Chart)などを作ってみたため、その方法記録しておく。

グループ棒グラフ (Grouped Bar Chart)

積上げ棒グラフの前にシンプルなグループ棒グラフから始める。

今回使うデータはEIAの「短期エネルギー見通し」(Short-Term Energy Outlook)のデータを加工して利用する。

データは下記のような形のDataFrameを使う。

(テーブルはDataFrameの一部をサンプルとして表示)

上記データを使って、シンプルなグループ棒グラフを作る。

データはdftという名前にしてある。

import pandas as pd
import cufflinks as cf
import plotly.graph_objects as go
from plotly.subplots import make_subplots as ms

fig = ms(rows=1,cols=1,specs=[[{'secondary_y':True}]])
fig.add_bar(x=dft.index,y=dft['OECD Consumption'],name='OECD Consumption')
fig.add_bar(x=dft.index,y=dft['Non-OECD Consumption'],name='Non-OECD Consumption')
fig.add_bar(x=dft.index,y=dft['OECD Production'],name='OECD Production')
fig.add_bar(x=dft.index,y=dft['Non-OECD Production'],name='Non-OECD Production')

fig.update_layout(template='plotly_dark',margin=dict(t=60,b=40),
                  title=dict(text=title,font=dict(size=20,color='white'),yanchor='top'),
                  barmode='group')
fig.update_yaxes(title_text='Production or Consumption')

上記のようにbarmode=’group’とするだけでよい。

チャートとしては、このように表示される。

Data Source : EIA

Cufflinksを使うえばより簡単に作成できる。

fig = dft[['OECD Consumption','Non-OECD Consumption']].tail(24).iplot(asFigure=True,kind='bar',barmode='group',theme='solar',opacity=0.8)

グループ積上げ棒グラフ (Stacked and Grouped Bar Chart)

上で作ったグループ棒グラフの消費と生産の二つのグループにし、積上げ棒グラフにしてみる。

fig = ms(rows=1,cols=1,specs=[[{'secondary_y':True}]])
fig.add_bar(x=dft.index,y=dft['OECD Consumption'],name='OECD Consumption',offsetgroup=1)
fig.add_bar(x=dft.index,y=dft['Non-OECD Consumption'],name='Non-OECD Consumption',offsetgroup=1,base=dft['OECD Consumption'])
fig.add_bar(x=dft.index,y=dft['OECD Production'],name='OECD Production',offsetgroup='two')
fig.add_bar(x=dft.index,y=dft['Non-OECD Production'],name='Non-OECD Production',offsetgroup='two',base=dft['OECD Production'])
fig.update_layout(legend=dict(orientation='h',y=-0.1,x=0,xanchor='left'),template='plotly_dark',margin=dict(t=60,b=40),title=dict(text=title,font=dict(size=20,color='white'),yanchor='top'))
fig.update_yaxes(title_text='Production or Consumption')
fig.update_yaxes(title_text='Production or Consumption')

offsetgroupを文字や数字で適当に指定し、グループ分けをする。

そして、それぞれのグループの積上げるベースをbase=hogeとして指定することで、グループ化された積上げ棒グラフを作成することができる。

この方法で作成はできるものの、作成したグラフ上でベースデータを非表示にした場合、不自然な表示のされ方になってしまう点という欠点がある。(修正方法は知りません)

サンプルグラフを張っておきます。(面倒で色を変えてなかったり、データ数の調整をしていないため、見づらいです。拡大してみていただくとわかりやすいかも)

Data Source : EIA

積上げ面グラフ (Stacked Area Chart)

OECD、Non-OECDの消費と生産をそれぞれ積上げ面グラフにし、サブプロットしてみる。

Data Source : EIA

作り方は下記の通り

fig = ms(rows=1,cols=2,horizontal_spacing=0.1,specs=[[{'secondary_y':True},{'secondary_y':True}]],subplot_titles=['Production','Consumption'])
fig.add_scatter(x=dft.index,y=dft['OECD Consumption'],name='OECD Consumption',row=1,col=1,stackgroup=1)
fig.add_scatter(x=dft.index,y=dft['Non-OECD Consumption'],name='Non-OECD Consumption',row=1,col=1,stackgroup=1)
fig.add_scatter(x=dft.index,y=dft['OECD Production'],name='OECD Production',row=1,col=2,stackgroup='two')
fig.add_scatter(x=dft.index,y=dft['Non-OECD Production'],name='Non-OECD Production',row=1,col=2,stackgroup='two')
fig.update_layout(legend=dict(orientation='h',y=-0.1,x=0,xanchor='left',traceorder='normal'),template='plotly_dark',margin=dict(t=60,b=40))
fig.update_yaxes(title_text='Production or Consumption',row=1,col=1,secondary_y=False)

stackgroupで適当な数字や文字列をふっておけばよい。

オーバーレイ面グラフ (Overlaid Area Chart)

呼び方はよくわからないが、重なりのある面グラフを作ってみる。

使用データはOECDとNon-OECDの合計消費と生産データを使う。

今回は第二Y軸(secondary_y)に余剰データを線グラフで追加もしてみる。

fig = ms(rows=1,cols=1,specs=[[{'secondary_y':True}]])
fig.add_scatter(x=dft.index,y=dft['Total Consumption'],name='World Consumption',fill='tozeroy')
fig.add_scatter(x=dft.index,y=dft['Total Production'],name='World Production',fill='tonexty')
fig.add_scatter(x=dft.index,y=dft['Total Surplus'],name='World Surplus',secondary_y=True)
fig.update_layout(template='plotly_dark',margin=dict(t=60,b=40),title=dict(text=title,font=dict(size=20,color='white'),yanchor='top'))
fig.update_yaxes(title_text='Production or Consumption',range=[80,105],secondary_y=False)
fig.update_yaxes(title_text='Surplus',range=[-20,20],secondary_y=True)

fill=’hoge’でゼロラインまで、もう一方のデータまでを塗りつぶすように指定するだけでよい。

Data Source : EIA