0

I am trying to input a single file that contains data from different packet streams (hence, different time values). I created a dataframe for each time and the data points/columns from each dataframe are plotted in single plot. I am not being able to get how to append the items in the legend to reflect the correct col names in the loop. This is what I have so far:

j = 0
tabs_df_list = []
## Creating source and figures for each df
for x in df_list:
    j += 1
    df_col_names = x.columns.to_numpy()
    col_names = df_col_names.tolist()
    source = "source"+str(j)
    source = ColumnDataSource(x)
## Create a figure for each df
    p = "p" + str(j)
    p = figure(title = 'Test Tlm Report',
           match_aspect = False,
           toolbar_location = 'right',
           height=750, width=1000,
           x_axis_label = 'Time [hh:mm]', # needs to correct time series
           y_axis_label = 'Data value')    # need to customize to tlm col

    tabs_temp = []
    items_list = []
    k = 1
    while k < len(col_names):
        r = "r" + str(k)
        r = p.line(x=col_names[0], y=col_names[k], source=source, line_width=2, line_color="lightseagreen", name=col_names[k], legend_label=col_names[k])
        r = p.scatter(x=col_names[0], y=col_names[k], source=source)
        items_list.append(col_names[k])
        items_list.append(r)
        tab = [TabPanel(child=p, title=col_names[0])]
        k += 1
   
        
    p.add_tools(HoverTool(tooltips=tooltips))
    legend = Legend(items=[items_list
                          ],location=(3, -25))
    p.add_layout(legend, 'right')
    
    p.legend.click_policy="mute"    
    
    tabs_df = "tabss" + str(j)
    tabs_df = Tabs(tabs=tab)
    tabs_df_list.append(tabs_df)
grid = gridplot (tabs_df_list, ncols=1)
show (grid)

The items list in the legend is what I do not know how to dynamically add to =/

1 Answer 1

0

In my opinion best practice is to define the Legend right after the figure() call and add each legend entry when creating a renderer using legend_item.

Minimal example:

Let's say this is our data:

import pandas as pd

df = pd.DataFrame({"x": [1,2,3], "a": [1,2,3], "b": [2,2,2], "c": [3,2,1]})

Then we can loop over the column names and add this name to the legend in a call like p.line() with legend_label=column_name.

from bokeh.models import Legend
from bokeh.palettes import d3
from bokeh.plotting import figure, show, output_notebook
output_notebook()

p = figure()
legend = Legend(click_policy='mute')
p.add_layout(legend, 'right')
for i, column_name in enumerate(df.columns):
    if column_name == 'x':
        continue
    p.line(df['x'], df[column], legend_label=column_name, color=d3['Category10'][10][i])
show(p)

Output:

line plot with legend

Comment:

If you use the same string for a legend label for multiple renderers, they are linked together in the legend und will be muted with just one click.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.