What I use is just
fig_list = []
grouped = df.unstack().groupby(level=1, axis=1)
for key in grouped.groups.keys():
tmp = grouped.get_group(key).droplevel([0, 1], axis=1)
fig = tmp.plot_bokeh(kind="line", title=key,
rangetool=True,
show_figure=False, **kwargs)
fig_list.append(fig)
and here is df.
('IC', 'IC00') | ('IC', 'IC01') | ('IC', 'IC02') | ('IC', 'IC03') | ('IF', 'IF00') | ('IF', 'IF01') | ('IF', 'IF02') | ('IF', 'IF03') | |
---|---|---|---|---|---|---|---|---|
(Timestamp('2023-01-03 00:00:00'), 1.0) | -2474 | nan | -1128 | -4424 | 3327 | nan | -3021 | -432 |
(Timestamp('2023-01-03 00:00:00'), 18.0) | -1056 | nan | 7373 | -1199 | -1948 | nan | -731 | -165 |
(Timestamp('2023-01-03 00:00:00'), 102.0) | 6613 | nan | 4045 | 2683 | 425 | nan | nan | nan |
(Timestamp('2023-01-03 00:00:00'), 131.0) | 2890 | nan | 5971 | 3882 | -84 | nan | 361 | nan |
(Timestamp('2023-01-03 00:00:00'), 1000.0) | 12068 | nan | 18309 | 17182 | 840 | nan | -2437 | 5518 |
(Timestamp('2023-01-04 00:00:00'), 1.0) | -2388 | nan | -996 | -4463 | 3053 | nan | -2650 | -388 |
(Timestamp('2023-01-04 00:00:00'), 18.0) | -563 | nan | 6464 | -1385 | -829 | nan | -1762 | 318 |
(Timestamp('2023-01-04 00:00:00'), 102.0) | 6309 | nan | 4350 | 1707 | 508 | nan | nan | nan |
(Timestamp('2023-01-04 00:00:00'), 131.0) | 2976 | nan | 5977 | 4001 | -66 | nan | 258 | nan |
Do u guys have any idea on how to add a MultiChoice widget to each fig in the for loop so that I can choose the id in a interactive way?
Actually I have no idea of bokeh itself. if I need to achieve the same result as plot_bokeh, what should I do, df.stack().stack().reset_index() first?
In pure Bokeh, you can handle it by using a widget along with a js callback. Below is a complete example with a Check Box Button - the plots will be hidden or displayed depending on the user's selection.
import pandas as pd
from bokeh.io import show, output_notebook
from bokeh.models import CustomJS, CheckboxButtonGroup, ColumnDataSource
from bokeh.plotting import figure
from bokeh.layouts import column, row
import random
import math
output_notebook()
def create_plots(doc):
# create toy dataframe
df = pd.DataFrame({
'datetime': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04'] * 3,
'id': ['id_1'] * 4 + ['id_2'] * 4 + ['id_3'] * 4,
'value': random.sample(range(1, 1000), 12)
})
ids = list(set(df['id']))
# create figure
plots = []
for id_ in ids:
source = ColumnDataSource(data=df[df['id'] == id_])
datetime = df[df['id'] == id_]['datetime']
p = figure(title=f"Plot for {id_}", x_range=datetime, height=300, width=300)
p.line(x='datetime', y='value', source=source)
p.xaxis.major_label_orientation = math.radians(45)
plots.append(p)
# create widget
checkbox_button_group = CheckboxButtonGroup(labels=ids, active=list(range(len(ids))))
callback = CustomJS(args=dict(plots=plots, chkbx=checkbox_button_group), code="""
for (let i = 0; i < plots.length; i++){
plots[i].visible = chkbx.active.includes(i)
}
""")
checkbox_button_group.js_on_change('active', callback)
doc.add_root(column(checkbox_button_group, row(plots)))
show(create_plots)
This code can be tested in a Jupyter notebook. I didn't try it with plot_bokeh
, though, as I'm not used to work with it.