階層構造のあるデータを可視化させたい場合、階層のつながりを残したまま図示したいけれども、まとめてしまうとグラフが細かくなりすぎて見にくくなってしまう... というように思ったことはありませんか?
Plotly では、それらを両立したままグラフを描くことができます!
そんな Plotly は 階層構造を持つデータの可視化をする方法は 下の3種類あります!
- Sunburst Charts (Plotly Sunburst Chart 描き方 まとめ ~ 円グラフ系の決定版! ~)
- Treemap Charts (今回の記事でまとめます!!)
- Icicle Charts (次回、記事にする予定です!)
グラフによってそれぞれ特徴がありますが、今回は Treemap の描き方についてまとめていきたいと思います!
Treemap とは?
Treemap とは、階層構造をもつデータを可視化するときの図の一つです!
各要素が占める割合に応じて、面積が与えられて可視化されるのは、円グラフとは同じですが、Treemap では、各要素は「長方形」で表されるのが特徴的です。
下の Plotly の 図は、各国別の人口を Treemap 化したものですが、今回はこの例を元に説明していきます!
実際に、"Asia"の部分をクリックすると、"Asia"の人口を 100%としたときの人口比率に対応する各国の人口を見ることができます! 右下の"Europe"などはそもそもの全体に占める割合が小さいので、Europeをクリックしてみると、 Europeの人口比率がよくわかりますね!
Treemap の基本的な描き方
階層構造のあるデータを可視化するために必要な情報は、labels, parents, values の 3つです!
これは、Treemap 以外の Sunburst Charts も Icicle Chart も同じです!
そして、グラフを描く上で一番良いポイントなのですが、グラフの描き方はほとんど同じです!
というより、 「go. の後の グラフの指定以外は 全く同じコードでも描くことができる」のです。このことを覚えておくと、1つのグラフの描き方をマスターするだけで3種類のグラフを描けるのでお得ですよ~
go.Treemap( 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']]])
Treemap 描き方 応用編
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.Treemap(
labels=df['labels'],
parents = df['parent'],
values = df['pop'],
branchvalues="total",
root_color="lightgrey"
))
fig.show()
コメント