使用Python Bokeh绘制多DataFrame:如何在循环中添加图例?
解决Bokeh循环中动态添加图例项的问题
你的核心问题是图例项的格式不符合Bokeh要求,Legend组件的items参数需要是元组列表,每个元组格式为(图例标签, [对应渲染器对象列表]),而你当前代码把标签和渲染器交替塞进同一个列表,导致图例无法正确识别。
关键修改点
- 分别保存折线和散点的渲染器:原代码会覆盖
r变量,丢失折线渲染器的引用,需要分开存储两个渲染器对象。 - 正确构造图例项列表:每次循环创建一个包含标签和对应两个渲染器的元组,添加到
items_list中。 - 修正Legend的items参数:直接传入构造好的元组列表,而非嵌套列表。
- 调整TabPanel创建位置:避免在循环中重复覆盖tab变量。
修正后的完整代码
j = 0 tabs_df_list = [] # 提前定义通用tooltips tooltips = [("Time", "@" + col_names[0]), ("Value", "@$name")] ## 为每个DataFrame创建数据源和图表 for x in df_list: j += 1 df_col_names = x.columns.to_numpy() col_names = df_col_names.tolist() source = ColumnDataSource(x) ## 创建图表对象 p = figure(title = 'Test Tlm Report', match_aspect = False, toolbar_location = 'right', height=750, width=1000, x_axis_label = 'Time [hh:mm]', y_axis_label = 'Data value') items_list = [] k = 1 while k < len(col_names): # 分别保存折线和散点的渲染器对象 line_r = p.line(x=col_names[0], y=col_names[k], source=source, line_width=2, line_color="lightseagreen", name=col_names[k]) scatter_r = p.scatter(x=col_names[0], y=col_names[k], source=source) # 构造符合要求的图例项元组,添加到列表 items_list.append((col_names[k], [line_r, scatter_r])) 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" # 每个图表对应一个TabPanel tabs_df = Tabs(tabs=[TabPanel(child=p, title=col_names[0])]) tabs_df_list.append(tabs_df) grid = gridplot(tabs_df_list, ncols=1) show(grid)
额外说明
- 如果需要给每个数据系列设置不同颜色,可以提前定义颜色列表(比如
colors = ["lightseagreen", "tomato", "royalblue"]),然后在循环中用line_color=colors[k-1]动态赋值。 - HoverTool中的
@$name会自动引用渲染器的name属性(即你设置的列名),实现通用的提示框,无需逐个修改。
内容的提问来源于stack exchange,提问作者Brain_overflowed
相关产品推荐
相关产品推荐

