Pythonライブラリ(ツリーマップ): squarify
1.概要
Treemap(面積グラフ)用ライブラリとしてsquarifyを紹介します。
1-1.ツリーマップ(面積グラフ)とは
Treemap(面積グラフ)とは、図の面積で数値の大小や割合を表現できるグラフになります。
統計学ではあまり見ないグラフですが特定条件での可視化には有効だと思います。
2.環境構築
ライブラリは”pip install squarify”でインストール可能です。
pip install squarify
3.API
3-1.squarify.plot()
Treemapを出力する”squarify.plot”のAPIは下記の通り。
[API]
squarify.plot(sizes, norm_x=100, norm_y=100, color=None, label=None, value=None,
ax=None, pad=False, bar_kwargs=None, text_kwargs=None, **kwargs)
sizes:入力値(リストや配列)。描画する四角形の面積を示す。
norm_x, norm_y:正規化のためのxとyの値。四角形の表示サイズを調整
color:色を指定(文字列orリスト形式)。Matplotlib-likeで色の指定可能
label:ラベルとして表示されるテキストのリストや配列。
value:値として表示されるテキストのリストや配列(sizeの値と同じ)
ax:Matplotlib の Axes インスタンス
pad:True にすると四角形の間に少しの間隔ができる
bar_kwargs(dict): matplotlib.Axes.bar に渡されるキーワード引数
text_kwargs(dict):matplotlib.Axes.text に渡されるキーワード引数
**kwargs
追加のキーワード引数は bar_kwargs にマージされる。
ここで明示的に提供される kwargs は優先される。
3-2.squarify.squarify()
Treemapの長方形情報を出力する"squarify.squarify"のAPIは下記の通り。
[API]
squarify.squarify(sizes, x, y, dx, dy)
size:
入力値(リストや配列)。描画する四角形の面積を示す。
数値は必ず正の値のこと
値はdescending(降順)にソート済みであること
値は総面積に対して正規化されること
x:原点のx座標
y:原点のy座標
dx:最大のdx幅
dy:最大のdy幅
4.Treemap作成:基礎編
4-1.Treemap作成:squarify.plot(sizes=values)
単純に数値の大小でTreemap作成するなら”squarify.plot(sizes=values)”となります。なお色は毎回ランダムで変更されます。
[IN]
import squarify
import matplotlib.pyplot as plt
values = [1, 10, 100, 500, 1000]
squarify.plot(sizes=values)
[OUT]
Matplotlibのaxis('off')を使用すると見た目がすっきりとします。
[IN]
values = [1, 10, 100, 500, 1000]
squarify.plot(sizes=values)
plt.axis('off')
plt.show()
[OUT]
4-2.ラベルの表示:label
ラベルを追加する場合はlabel引数にリストを渡します。
[IN]
values = [1, 10, 100, 500, 1000]
labels = ['A', 'B', 'C', 'D', 'E']
squarify.plot(sizes=values, label=labels)
plt.axis('off')
plt.show()
[OUT]
4-3.色の設定:color/alpha
4-3-1.カラーリストを自作
色を指定する場合はcolor引数、透明度はalpha引数で指定します。
[IN]
values = [1, 10, 100, 500, 1000]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['red', 'green', 'blue', 'yellow', 'orange']
squarify.plot(sizes=values, label=labels, color=colors, alpha=0.5)
plt.axis('off')
plt.show()
[OUT]
【色の設定方法】
色はMatplotlibのカラーマップから選択が可能です。
4-3-2.colormapを取得
項目数が増えると手動でリストを作成するのは手間となります。そこでmatplotlibのcm(Colormap)を使用して好きな色を取得したいと思います。
例としてplt.cmで色のマップを取得できます。
[IN]
plt.cm.tab20
[OUT]
メソッドとして"np.linspace(0, 1, <データ数>)"を渡すことで色を数値のリストとして取得できます。
[IN]
import numpy as np
plt.cm.tab20(np.linspace(0, 1, 10))
[OUT]
array([[0.12156863, 0.46666667, 0.70588235, 1. ],
[1. , 0.49803922, 0.05490196, 1. ],
[0.17254902, 0.62745098, 0.17254902, 1. ],
[0.83921569, 0.15294118, 0.15686275, 1. ],
[0.58039216, 0.40392157, 0.74117647, 1. ],
[0.76862745, 0.61176471, 0.58039216, 1. ],
[0.96862745, 0.71372549, 0.82352941, 1. ],
[0.78039216, 0.78039216, 0.78039216, 1. ],
[0.85882353, 0.85882353, 0.55294118, 1. ],
[0.61960784, 0.85490196, 0.89803922, 1. ]])
実装すると下記の通りとなります。
[IN]
values = [1, 10, 100, 500, 1000]
labels = ['A', 'B', 'C', 'D', 'E']
colors = plt.cm.tab20(np.linspace(0, 1, len(values)))
squarify.plot(sizes=values, label=labels, color=colors)
plt.axis('off')
plt.show()
[OUT]
4-4.値の表示:value
値を表示する場合はvalue引数を使用します。ここではsizesと同じ値を渡しました。
[IN]
values = [1, 10, 100, 500, 1000]
labels = ['A', 'B', 'C', 'D', 'E']
colors = ['red', 'green', 'blue', 'yellow', 'orange']
squarify.plot(sizes=values,
label=labels,
color=colors,
value=values)
plt.axis('off')
plt.show()
[OUT]
5.実践編
5-1.サンプルデータ取得
今回のサンプルデータとしては「国税庁の都道府県別合計所得階級別人数」を使用します。
可視化しやすいように辞書型に変換しておきます。
[IN]
import pandas as pd
import matplotlib.pyplot as plt
#高所得者のデータ抽出
url = 'https://www.nta.go.jp/publication/statistics/kokuzeicho/shinkoku1998/07.htm' #国税庁:申告所得金額階級別表
dfs = pd.read_html(url)
_df = dfs[-1]
df = _df[ [('区分', '都道府県'), ('合計所得階級別', '5,000万円 超')] ]
df.columns = df.columns.get_level_values(1) #マルチインデックスを解除:2階層目のラベルを取得
#都道府県から"計"と"全国計"を除外
df = df[~df['都道府県'].isin(['計', '全国計'])]
data_dict = df.set_index('都道府県')['5,000万円 超'].to_dict()
data_dict
[OUT]
{'東京': 10878,
'神奈川': 3917,
'千葉': 1846,
'山梨': 180,
'埼玉': 2236,
'茨城': 560,
'栃木': 514,
'群馬': 424,
'長野': 465,
'新潟': 408,
'大阪': 3192,
'京都': 918,
'兵庫': 2288,
'奈良': 474,
'和歌山': 263,
'滋賀': 246,
'北海道': 1039,
'宮城': 530,
'岩手': 229,
'福島': 376,
'秋田': 204,
'青森': 263,
'山形': 224,
'愛知': 3099,
'静岡': 1281,
...
'熊本': 341,
'大分': 247,
'鹿児島': 246,
'宮崎': 199,
'沖縄': 236}
5-2.実装編
上記データをTreemapで可視化したいと思います。綺麗にするために下記のように調整しました。
axを指定して図のサイズを調整、タイトル追加
日本語の文字化け防止に"japanize_matplotlib"をインポート
plt.cmによるColormapによる色分け
label, valueで都道府県名と数値を表示
padを指定して面積の空間を設定
[IN]
import squarify
import matplotlib.pyplot as plt
import japanize_matplotlib
import numpy as np
fig, ax = plt.subplots(figsize=(12, 8))
colors = plt.cm.tab20(np.linspace(0, 1, len(data_dict)))
squarify.plot(sizes=data_dict.values(),
label=data_dict.keys(),
value=data_dict.values(),
ax=ax,
color=colors,
pad = True)
plt.axis('off')
plt.title('都道府県別の高所得者数(5,000万円超)', fontsize=20)
plt.show()
[OUT]
ほぼ完成ですが少し見栄えが悪いです。最後に値を降順(descending)にして表示します。これにより並びと色に関連が出て見やすいくなりました。
[IN]
datadict_sorted = dict(sorted(data_dict.items(), key=lambda item: item[1], reverse=True))
fig, ax = plt.subplots(figsize=(12, 8))
colors = plt.cm.tab20(np.linspace(0, 1, len(datadict_sorted)))
squarify.plot(sizes=datadict_sorted.values(),
label=datadict_sorted.keys(),
value=datadict_sorted.values(),
ax=ax,
color=colors,
pad = True)
plt.axis('off')
plt.title('都道府県別の高所得者数(5,000万円超)', fontsize=20)
plt.show()
[OUT]
参考資料
あとがき
割合は円グラフや積み上げグラフでよいけど、何らかの表示には使えそう。もう少し色々調整できるなら特許マップとかにも使えそうだけど・・・・