0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

plotlyでbubble-pieチャート作成

Last updated at Posted at 2023-07-06

1.はじめに

  • pie-bubbleチャートという種類のグラフをplotlyで作成した。
  • 自分の欲しい機能を追加していきたい(簡単なcallbackとか)

2.経緯

  • bubble-pieチャートというのがあって、昔から試作を繰り返しては、きれいさとかグラフの動作で不満な部分があってずっと検討していた。

  • 一番惜しかったのが、zingchart。が、円グラフの内訳の数字がうまく出せず断念。

  • javascriptで
    image.png

  • Rで
    image.png

  • python(matplotlib)で
    image.png


  • もっと動的にきれいに出したいなとか、軸などきれいに設定したいと思いつつ過ごしていたところ、plotlyをヘビーに使っていたのに鑑みて、plotlyで作成してみた。
  • 最終的にできたのがこんな感じ↓
    image.png

plotyなので、内訳をいくつか除いてもすぐに再描画してくれる。

image.png

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
    ここも苦労したけど、描画するデータラベルとの関係で書きにくいので省略。

4.その他・今後追加したい機能

  • ここここに書いてあるような簡単なイベント機能で、選択エリアの関連データをdataframeなどで出せるようにしたい。dash使えば、という自分の声もありますが。
  • 現状の出し方だと、plotlyの利点であるズームボタンとかエリア選択が利用不可能になってしまっていたので、復活させたい。
  • plotly expressを使って時系列変化もできるようにしたい。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?