階層構造のあるデータを可視化させたい場合、階層のつながりを残したまま図示したいけれども、まとめてしまうとグラフが細かくなりすぎて見にくくなってしまう... というように思ったことはありませんか?
Plotly では、それらを両立したままグラフを描くことができます!
そんな Plotly は 階層構造を持つデータの可視化をする方法は 下の3種類あります!
- Sunburst Charts (Plotly Sunburst Chart 描き方 まとめ ~ 円グラフ系の決定版! ~)
- Treemap Charts (Plotly Tree map で階層化データを可視化! 描き方まとめ)
- Icicle Charts (今回の記事です!!)
これまで、2つのグラフをまとめてきましたが、この記事では第3弾として plotly の version 5.0 から新しく追加された Icicle Charts についてまとめていきます!
Icicle Charts とは?
Icicle Charts とは、階層構造をもつデータを可視化するときの図の一つなのですが、" Icicle " というのは和訳すると、「つらら」という意味になる通り、階層的に分岐していく様子がつららに似ていることからこの名前がついているらしいです。
他の 階層構造をもつデータを可視化するときの図 である Sunburst Charts や Treemap と比較をしてみると、いずれも 各要素が占める割合に応じて、面積が与えられて可視化されるのは同じですが、描画する形状に違いがあります。
- Sunburst Charts : 円
- Treemap : 長方形 (内包型)
- Icicle Charts : 長方形
Icicle Charts は 円グラフを直線上 (長方形)に変形しているような形という部分と子の要素が親の要素の外側に描画されているという点は、Sunburst Chartsに似ています! その一方、 Treemap では、子の要素は親の要素の内側に内包されるような形で描画されるところは、同じ長方形型に可視化されている Icicle Chartsと異なる部分ですね!
ちなみに、このグラフは2021年6月にリリースされたplotly の version 5 の新機能になります!
Icicle Charts の基本的な描き方
階層構造のあるデータを可視化するために必要な情報は、labels, parents, values の 3つです!
これは、Icicle Charts 以外の Sunburst Charts も Treemap も同じです!
そして、グラフを描く上で一番良いポイントなのですが、グラフの描き方はほとんど同じです!
というより、 「go. の後の グラフの指定以外は 全く同じコードでも描くことができる」のです。このことを覚えておくと、1つのグラフの描き方をマスターするだけで3種類のグラフを描けるのでお得ですよ~
go.Icicle( 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()
# 各大陸の parent (親要素)は total に設定
df_2007_continent['parents'] = "total"
# 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']]])
# 合計 (total)を表す行を追加
df = df.append({'labels':'total','parent':'', 'pop':df_2007_continent['pop'].sum()},ignore_index=True)
③ 子の要素の定義
最下位層ではなければ、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']]])
Icicle Charts 描き方 応用編
root_color (根の 色設定)
root 部分の背景色設定ですが、デフォルト設定だと、白っぽい色で背景と同化してしまうので見にくくなってしまいます。なので、私のおすすめとしては、 "lightgray"に色を変えてみること。上の図でもそのように設定していますが、それだけでグラフの見やすさが上がります!
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()
df = pd.DataFrame(columns={'labels','parent','pop'})
df_2007_continent['parent'] = "total" # 各大陸の parent (親要素)は total に設定
df_2007_continent = df_2007_continent.rename(columns={'continent':'labels'})
df = pd.concat([df,df_2007_continent[['labels','parent','pop']]])
df_2007 = df_2007.rename(columns={'country':'labels','continent':'parent'})
df = pd.concat([df,df_2007[['labels','parent','pop']]])
# 合計 (total)を表す行を追加
df = df.append({'labels':'total','parent':'', 'pop':df_2007_continent['pop'].sum()},ignore_index=True)
fig =go.Figure(go.Icicle(
labels=df['labels'],
parents = df['parent'],
values = df['pop'],
branchvalues="total",
root_color="lightgrey"
))
fig.show()
コメント