0
0

bokeh: `MultiChoice` widgetを使って、特定の折れ線を目立たせる

Last updated at Posted at 2024-05-22

環境

  • Python 3.12.1
  • bokeh 3.4.2

やりたいこと

bokehを使って、10本以上の折れ線を描画しています。

import bokeh
import numpy
from bokeh.plotting import figure, output_file, save
import bokeh.palettes


x_data = numpy.arange(-20, 20, 0.1)
palette = bokeh.palettes.Category10[10]
fig = figure(x_axis_label="x", y_axis_label="y", width=600, height=400)

for i in range(10):
    legend_label = f"y=sin(x + {i})"
    fig.line(
        x_data,
        numpy.sin(x_data + i),
        color=palette[i],
        legend_label=legend_label,
    )

fig.legend.click_policy = "hide"
# 凡例をグラフの外に配置する
legend = fig.legend[0]
fig.add_layout(legend, "left")

output_file("graph1.html")
save(fig)

image.png

折れ線が重なり合っているので、たとえば y=sin(x + 5)の折れ線がどれなのか、ぱっと見分かりません。
なので、特定の折れ線を目立つように表示したいです。

やったこと

MultiChoice widgetを使って、折れ線を選択できるようにしました。
選択された折れ線は、線を太くして目立たせました。

import bokeh
import numpy
from bokeh.plotting import figure, output_file, save
import bokeh.palettes
from bokeh.models import CustomJS
from bokeh.models.renderers.glyph_renderer import GlyphRenderer
from bokeh.models.widgets.inputs import MultiChoice
from typing import Final

DEFAULT_LINE_WIDTH: Final[int] = 1


def create_multi_choice_widget(line_glyphs: dict[str, GlyphRenderer]) -> MultiChoice:
    args = {"lineGlyphs": line_glyphs}
    SELECTED_LINE_WIDTH: Final[int] = 4

    code = f"""
    const selectedLegendLabel = this.value;
    for (let legendLabel in lineGlyphs) {{
        if (selectedLegendLabel.includes(legendLabel)) {{
            lineGlyphs[legendLabel].glyph.line_width = {SELECTED_LINE_WIDTH};
        }} else {{
            lineGlyphs[legendLabel].glyph.line_width = {DEFAULT_LINE_WIDTH};
        }}
    }}
    """

    options = list(line_glyphs.keys())
    multi_choice = MultiChoice(options=options, title="Find:", width=300)
    multi_choice.js_on_change(
        "value",
        CustomJS(code=code, args=args),
    )
    return multi_choice


x_data = numpy.arange(-20, 20, 0.1)
palette = bokeh.palettes.Category10[10]
fig = figure(x_axis_label="x", y_axis_label="y", width=600, height=400)

line_glyphs: dict[str, GlyphRenderer] = {}
for i in range(10):
    legend_label = f"y=sin(x + {i})"
    line_glyphs[legend_label] = fig.line(
        x_data,
        numpy.sin(x_data + i),
        color=palette[i],
        legend_label=legend_label,
        line_width=DEFAULT_LINE_WIDTH,
    )

fig.legend.click_policy = "hide"
# 凡例をグラフの外に配置する
legend = fig.legend[0]
fig.add_layout(legend, "left")

output_file("graph.html")
multi_choice_widget = create_multi_choice_widget(line_glyphs)
save([fig, multi_choice_widget])

image.png

折れ線を選択すると、線が太くなり目立つようになりました。また凡例に表示されている線も自動的に太くなりました。

関連するサイト

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