前の記事 では、円グラフの描き方についてまとめていきました。他のグラフと違って、x,y軸の設定ではなく、要素となる label と その値となる value の 2つが基本要素となっていましたが、今回の記事ではそのような知識を土台として、plotly でよりグラフを活用するためにマスターしておくと良いグラフ "Sunburst Chart" についてまとめていきます。 これを使えるようになることで、「複雑な円グラフ・複数の円グラフを一つにまとめることが可能」になります!!
Sunburst 図とは?
Sunburst図とは、階層型のグラフの一つです。下の国別人口グラフを例にあげて今回の記事ではまとめていこうと思います。このグラフでは、内側の円には大陸・地域別、そして外側の円には国別というように分かれていますよね。このように中心に親(根)となる要素があり、その子を階層的に表現する円グラフのことをSunburst 図といい、これを活用することで階層のある要素を一つの円グラフにまとめることができるのが特徴です。
しかし、1つにまとめることのデメリットとすると、下の階層にいけば行くほど占める面積が小さくなってしまうので、見にくくなってしまうという問題です。実際に、下のグラフで Europe(ヨーロッパ)の国をどのくらい見えますか?10カ国をみることでさえ至難の業のように思えますが、Plotlyでは解決することができます!
内側のグラフの Europeの部分をクリックしてみてください。そうすることで、Europeの全人口を100%としたときの円グラフを書くことができました! この状態で10カ国見ることは簡単ですよね!
元に戻るときは、真ん中のEuropeをクリックすると元のSunburst 図に戻るので、何階層に分けても後で確認することが簡単にできます!!
Sunburst図の基本的な描き方
円グラフで必要な最低限の要素はlabelsとvaluesの2つで次のように書きました。
go.Pie(labels="分類したいラベルのリスト", values="値のリスト")
Sunburst図では、それに加えて親の要素(ラベル)を指定する必要があるので、最低限の構造は次のようになります。
go.Sunburst(labels="分類したいラベルのリスト",
parents="親のラベルのリスト",
values="値のリスト")
円グラフと違う点は、親のラベルを明記したカラムが必要な点と、根となる要素の定義が必要になってくるという部分です。やっていることとしては難しくはないので例を用いて順に説明していきます!
① 描画用のデータフレームを定義
# label, parents, value(今回はpop(人口)がグラフで描画したい値)のdfを作る
df = pd.DataFrame(columns={'labels','parents','pop'})
② 根の定義
親となる要素をgroupbyによりまとめた上で、最上位の要素のparentsには何も設定しない ("”を代入)
# 親となる要素をgroupbyによりまとめる
df_2007_continent = df_2007.groupby('continent').sum().reset_index()
# 最上位の要素のparentsには何も設定しない ("”を代入)
df_2007_continent['parents'] = ""
# labelとなる continentカラムをlabelsにrenameした上で描画用のdfに結合
df_2007_continent = df_2007_continent.rename(columns={'continent':'labels'})
df = pd.concat([df,df_2007_continent[['labels','parents','pop']]])
③ 子の要素の定義
最下位層ではなければ、gropubyをしてその合計を求めたうえで描画用のdfに加え、最下位層の場合はdfに合うように改名した後で、dfにconcatして加える。
# countryカラムをlabelsに、continentカラムをparentsにそれぞれrenameした上で描画用のdfに結合
df_2007 = df_2007.rename(columns={'country':'labels','continent':'parents'})
df = pd.concat([df,df_2007[['labels','parents','pop']]])
Sunburst図 描き方 応用編
branchvalues (子要素の幅の設定)
- total (例であげているグラフはこちら)
子要素の幅は、親の要素に含まれている割合だけで決定 (親の幅は子の幅の合計) - remainder (デフォルト)
親の幅は子の幅の和に親の幅を足したもの、つまり子の幅の和の合計は最大でも親の幅の半分
ちなみに、上のグラフをデフォルトで描いてみると下の図のようになる。
サンプルコード
ここまでの内容をまとめてコードに書くと下のようになります。
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
# データの準備
df = px.data.gapminder()
df_2007 = df[df['year']==2007]
df_2007_continent = df_2007.groupby('continent').sum().reset_index()
# parents(親子関係)を明確にしたデータフレームを作成
df = pd.DataFrame(columns={'labels','parents','pop'})
df_2007_continent['parents'] = ""
df_2007_continent = df_2007_continent.rename(columns={'continent':'labels'})
df = pd.concat([df,df_2007_continent[['labels','parents','pop']]])
df_2007 = df_2007.rename(columns={'country':'labels','continent':'parents'})
df = pd.concat([df,df_2007[['labels','parents','pop']]])
fig =go.Figure(go.Sunburst(
labels=df['labels'],
parents = df['parents'],
values = df['pop'],
branchvalues="total",
))
fig.show()
コメント