1

I was consulting the bokeh user guide (link) on creating interactive legends (see subsection on "Hiding glyphs").

The code given allows me to create up to 4 stacked line charts. For example, if I try to create a fifth line chart ("AAP"):

p = figure(width=800, height=250, x_axis_type="datetime")
p.title.text = 'Click on legend entries to hide the corresponding lines'

import pandas as pd

from bokeh.palettes import Spectral4
from bokeh.plotting import figure, show
from bokeh.sampledata.stocks import AAPL, GOOG, IBM, MSFT

for data, name, color in zip([AAPL, GOOG, IBM, MSFT, AAPL], ["AAPL", "GOOG", "IBM", "MSFT", "AAP"], Spectral4):
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['date'])
    p.line(df['date'], df['close'], line_width=2, color=color, alpha=0.8, legend_label=name)

p.legend.location = "top_left"
p.legend.click_policy="hide"
show(p)

it will still only show four.

I was wondering if it is possible to extend this code and create many more line charts (say 20) and if so, how this can be done.

Thank you

mosc9575
  • 5,618
  • 2
  • 9
  • 32
Ebbinghaus
  • 95
  • 6

1 Answers1

2

Your approach is working fine and would work, if you use Spectral5 instead of Spectral4 as palette. You have to know, that zip iterates over all lists and stops if one list has no more items. That was the case.

Minimal working example:

import pandas as pd

from bokeh.plotting import figure, show, output_notebook
from bokeh.sampledata.stocks import AAPL, GOOG, IBM, MSFT
output_notebook()

p = figure(width=800, height=250, x_axis_type="datetime")
p.title.text = 'Click on legend entries to hide the corresponding lines'

dataset = [AAPL, GOOG, IBM, MSFT, AAPL]
nameset = ["AAPL", "GOOG", "IBM", "MSFT", "AAP"]
colorset = ['blue', 'red', 'green', 'magenta', 'black']

for data, name, color in zip(dataset, nameset, colorset):
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['date'])
    p.line(df['date'], df['close'], line_width=2, color=color, alpha=0.8, legend_label=name)

p.legend.location = "top_left"
p.legend.click_policy="hide"
show(p)

Output:

5 lines

Comment

For this I used bokeh 2.4.3 but with bokeh 3.+ this should work, too.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
mosc9575
  • 5,618
  • 2
  • 9
  • 32
  • Thanks for the comment. Unfortunately, I've tried your suggestion previously and it didn't work. Replacing "Spectral4" with "Spectral5" will return "NameError: name 'Spectral5' is not defined". I am also confident the lists are of identical lengths; they were datasets used in bokeh's user guide afterall (and I checked the length). – Ebbinghaus Jan 23 '23 at 08:33
  • In my Version of bokeh a palette named `Spectral5` exists. It is a list with this value: `['#2b83ba', '#abdda4', '#ffffbf', '#fdae61', '#d7191c']`. Nevertheless you can define your own list with 5 elements and give it a try. There ary many more [palettes](https://docs.bokeh.org/en/latest/docs/reference/palettes.html) in bokeh. – mosc9575 Jan 23 '23 at 08:39