1.はじめに
- pie-bubbleチャートという種類のグラフをplotlyで作成した。
- 自分の欲しい機能を追加していきたい(簡単なcallbackとか)
2.経緯
-
bubble-pieチャートというのがあって、昔から試作を繰り返しては、きれいさとかグラフの動作で不満な部分があってずっと検討していた。
-
一番惜しかったのが、zingchart。が、円グラフの内訳の数字がうまく出せず断念。
plotyなので、内訳をいくつか除いてもすぐに再描画してくれる。
3.ソース
全体のソースコードはここから
ポイントは
- 円グラフを描画するGrid(メッシュ)の作り方
go.pie()の引数として指定しないといけないのが、
・label(円グラフの中の内訳)
・domain (各円グラフに対応するグラフ上の4点指定のエリア)
・values(各円グラフの内訳に対応する件数.リスト形式で)
の3つ。
例えば
labels=["hydrogen","oxygen","co2","methane"]
val = [1,3,2,4]
domain = [
{'x': [0.0, 0.5], 'y': [0.0, 0.5]},
{'x': [0.0, 0.5], 'y': [0.5,1.0]},
{'x': [0.5, 1.0], 'y': [0.0, 0.5]},
{'x': [0.5, 1.0], 'y': [0.5, 1.0]},
]
go.Pie(labels = labels,
values = val,
domain = domain,
)
のような形。domainが一番理解しにくかったですが、パネルを置いてくイメージで。
x軸のリスト(下の例だとkai_list)と、y軸のリスト(kadai_list)があった場合に、
len(arr1) * len(arr2)のメッシュをうまくdomainsにはまるように生成させるのが下記の2関数。np.linspaceとitertoolsを活用。
import numpy as np
def getrangearr(num: int = 5) -> np.ndarray:
"""
num個の点からなる範囲の配列を返します。
Args:
num: 点の数 (デフォルト: 5)
Returns:
num個の点からなる範囲の配列
"""
start = 0
stop = 1
lins = np.linspace(start, stop, num)
mesh = []
for i in range(len(lins) - 1):
mesh.append([lins[i], lins[i + 1]])
return np.array(mesh)
import itertools as it
import numpy as np
def getmesh(arr1: List[int], arr2: List[int]) -> List[List[int]]:
"""
arr1とarr2の全組み合わせを返します。
Args:
arr1: 配列1
arr2: 配列2
Returns:
arr1とarr2の全組み合わせのリスト
"""
combi = []
combinations = it.product(arr1, arr2)
for combination in combinations:
combi.append(combination)
return combi
xlen = len(kai_list) + 1
ylen = len(kadai_list) + 1
xarr = getrangearr(xlen)
yarr = getrangearr(ylen)
meshd = getmesh(xarr,yarr)
domains = [{'x':mesh[0],'y':mesh[1]} for mesh in meshd]
- 罫線のかけ方
x軸、y軸ともにレンジを[0,1]にした関係で、通常の罫線が不要になり、各円グラフの中心をとおるxyの罫線を追加する部分で苦労。
最終的に
for i,xpos in enumerate(xarr):
fig.add_vline(x=(xpos[0] + xpos[1])/2, line_width=0.3, line_dash="dash",line_color="gray")
for i,ypos in enumerate(yarr):
fig.add_hline(y=(ypos[0] + ypos[1])/2, line_width=0.3, line_dash="dash",line_color="gray")
のようにして、各円グラフの中心を通る破線を描画して、その上に各円グラフを載せていくように設定!
- add_annotation
ここも苦労したけど、描画するデータラベルとの関係で書きにくいので省略。